<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Series on Why No Test Flight</title>
    <link>https://whynotestflight.com/series/</link>
    <description>Recent content in Series on Why No Test Flight</description>
    <generator>Hugo -- gohugo.io</generator>
    <language>en-us</language>
    <lastBuildDate>Mon, 24 Nov 2025 00:00:00 +0000</lastBuildDate>
    
	<atom:link href="https://whynotestflight.com/series/index.xml" rel="self" type="application/rss+xml" />
    
    
    
    <item>
      <title>Okay, how bad can getting client HTTPS to work be really?</title>
      <link>https://whynotestflight.com/excuses/okay-how-bad-can-getting-client-https-to-work-be-really/</link>
      <pubDate>Mon, 24 Nov 2025 00:00:00 +0000</pubDate>
      
      <guid>https://whynotestflight.com/excuses/okay-how-bad-can-getting-client-https-to-work-be-really/</guid>
      <description>&lt;p&gt;My chosen deployment method for the server part of my Swift-IoT-Hello project, a Digital Ocean App Server, ONLY does HTTPS connections. Meanwhile my client can only handle HTTP.&lt;/p&gt;
&lt;p&gt;I could get around this a few ways. Many of them versions of:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;creating a local device gateway of some flavor&lt;/li&gt;
&lt;li&gt;configuring a more permissive external server (as the main or as a proxy)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Those types of solutions push the complexity into the project&amp;rsquo;s architecture in a way that might make it difficult for a student or beginner to spin up. IF I can get HTTPS working the complexity will feel more invisible, perhaps.&lt;/p&gt;
&lt;p&gt;So that leaves trying spending at least &lt;em&gt;some&lt;/em&gt; time to trying to get HTTPS to work.&lt;/p&gt;
&lt;p&gt;For some chips HTTPS would be too much math and too much storage space, but the ESP32-C6 should be able to do it. At this stage, most things that can run Embedded Swift at all can probably do it.&lt;/p&gt;
&lt;p&gt;So what does that look like? Here&amp;rsquo;s my initial todo list and some of resources I&amp;rsquo;ll need to get it done.&lt;/p&gt;
&lt;p&gt;TODO:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;input checked=&#34;&#34; disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; watch some videos&lt;/li&gt;
&lt;li&gt;&lt;input disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; do an esp-idf only https client example&lt;/li&gt;
&lt;li&gt;&lt;input disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; (optional) do a pico sdk only https example&lt;/li&gt;
&lt;li&gt;&lt;input disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; study SwiftNIO and it&amp;rsquo;s TLS library&lt;/li&gt;
&lt;li&gt;&lt;input disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; look at my existing (and other&amp;rsquo;s) Swift clients&lt;/li&gt;
&lt;li&gt;&lt;input disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; Look at some API packages / type-only packages&lt;/li&gt;
&lt;li&gt;&lt;input checked=&#34;&#34; disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; choose a C framework&lt;/li&gt;
&lt;li&gt;&lt;input disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; go&amp;hellip;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;watch-some-videos&#34;&gt;Watch Some Videos&lt;/h2&gt;
&lt;p&gt;For instruction and reference I prefer written articles, but for orienting myself to a space I like video.&lt;/p&gt;
&lt;p&gt;Before creating an implementation I want refresh my memory / understand current best practices on the TLS handshake which distinguishes HTTPS from HTTP.&lt;/p&gt;
&lt;p&gt;Here are some videos that help clarify the problems involved. The first one a lone is enough for the already conversant. It&amp;rsquo;s both specific to the exact topic and an overview. At the end is an &amp;ldquo;off-topic&amp;rdquo; but interesting discussion of &lt;a href=&#34;https://rust-lang.org&#34;&gt;Rust&lt;/a&gt; and &lt;a href=&#34;https://www.zephyrproject.org&#34;&gt;Zephyr&lt;/a&gt;.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The Linux Foundation
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://www.youtube.com/watch?v=C7snRkLbIWM&#34;&gt;IoT TLS: Why It&amp;rsquo;s Hard - David Brown, Linaro&lt;/a&gt; (7 y.o.) Great great overview.&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/zephyrproject-rtos/zephyr/blob/main/subsys/net/lib/sockets/sockets_tls.c&#34;&gt;Zephyr TLS implementation&lt;/a&gt; uses &lt;a href=&#34;https://github.com/zephyrproject-rtos/zephyr/tree/main/modules/mbedtls&#34;&gt;mbed-tls&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Computerphile:
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://www.youtube.com/@Computerphile/search?query=TLS&#34;&gt;https://www.youtube.com/@Computerphile/search?query=TLS&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://www.youtube.com/watch?v=0TLDTodL7Lc&#34;&gt;Transport Layer Security (TLS)&lt;/a&gt; (5 y.o.)&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://www.youtube.com/watch?v=86cQJ0MMses&#34;&gt;TLS Handshake Explained&lt;/a&gt; (5 y.o.)&lt;/li&gt;
&lt;li&gt;Ellip&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://www.youtube.com/watch?v=NmM9HA2MQGI&#34;&gt;Secret Key Exchange (Diffie-Hellman)&lt;/a&gt; (perhaps a bit extra, 7 y.o.)&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://www.youtube.com/watch?v=GSIDS_lvRv4&#34;&gt;Public Key Cryptography&lt;/a&gt; (perhaps a bit extra)&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://www.youtube.com/watch?v=s22eJ1eVLTU&#34;&gt;What are digital signatures&lt;/a&gt; (4 y.o.)&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://www.youtube.com/watch?v=vsXMMT2CqqE&#34;&gt;Key Exchange Problems&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://www.youtube.com/watch?v=NF1pwjL9-DE&#34;&gt;Elliptic Curves&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://www.youtube.com/watch?v=DMtFhACPnTY&#34;&gt;SHA: Secure Hashing Algorithm&lt;/a&gt; (perhaps a bit extra)&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://www.youtube.com/watch?v=PG9oKZdFb7&#34;&gt;Network Stacks and the Internet&lt;/a&gt; (if this isn&amp;rsquo;t familiar, 12 y.o.)&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://www.youtube.com/watch?v=E_wX40fQwEA&#34;&gt;Secure Web Browsing&lt;/a&gt; (if this isn&amp;rsquo;t familiar, 9 y.o.)&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://www.youtube.com/watch?v=keo0dglCj7I&#34;&gt;What happens when you click a link?&lt;/a&gt; (most basic DNS/TCP/HTTP recap, 10 y.o.)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Practical Networking
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://www.youtube.com/watch?v=0ylxXrN1yHs&#34;&gt;TLS 1.3&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Mongoose Networking Library
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://www.youtube.com/watch?v=kCMs_L1yzPw&#34;&gt;TLS for microcontrollers explained&lt;/a&gt; mostly a recap of tls in general until about 5:35
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://mongoose.ws&#34;&gt;https://mongoose.ws&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Hitex
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://www.youtube.com/watch?v=kgVhrEVrlkA&#34;&gt;Hitex Webinar Secure communication for IoT devices with Mbed TLS&lt;/a&gt; (long, good overview but not example code)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Misc Off Topic
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://ossna2025.sched.com/event/1zff7/why-rust-and-zephyr-are-a-good-fit-david-brown-linaro&#34;&gt;https://ossna2025.sched.com/event/1zff7/why-rust-and-zephyr-are-a-good-fit-david-brown-linaro&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;A couple little text items to add because not a lot of decent video on it 1.2 vs 1.3:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://www.cloudflare.com/learning/ssl/why-use-tls-1.3/&#34;&gt;https://www.cloudflare.com/learning/ssl/why-use-tls-1.3/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://www.dchost.com/blog/en/updates-to-tls-1-3-standards-and-what-they-mean-for-your-servers/&#34;&gt;https://www.dchost.com/blog/en/updates-to-tls-1-3-standards-and-what-they-mean-for-your-servers/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;do-a-couple-of-hello-worlds-on-the-chips-ill-use&#34;&gt;Do a couple of hello worlds on the chips I&amp;rsquo;ll use&lt;/h2&gt;
&lt;p&gt;The espidf and the pico sdk both have https client examples that I&amp;rsquo;ll get rolling just to make sure there aren&amp;rsquo;t hardware/tool chain problems waiting to bite me.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://docs.espressif.com/projects/esp-idf/en/stable/esp32/api-reference/protocols/esp_http_client.html&#34;&gt;https://docs.espressif.com/projects/esp-idf/en/stable/esp32/api-reference/protocols/esp_http_client.html&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://docs.espressif.com/projects/esp-idf/en/v5.2/esp32c6/api-reference/protocols/mbedtls.html&#34;&gt;https://docs.espressif.com/projects/esp-idf/en/v5.2/esp32c6/api-reference/protocols/mbedtls.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/espressif/esp-idf/tree/v5.2/examples/protocols/https_mbedtls&#34;&gt;https://github.com/espressif/esp-idf/tree/v5.2/examples/protocols/https_mbedtls&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;(compare to rust) &lt;a href=&#34;https://github.com/esp-rs/esp-mbedtls&#34;&gt;https://github.com/esp-rs/esp-mbedtls&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/raspberrypi/pico-examples/tree/4c3a3dc0196dd426fddd709616d0da984e027bab/pico_w/wifi/tls_client&#34;&gt;https://github.com/raspberrypi/pico-examples/tree/4c3a3dc0196dd426fddd709616d0da984e027bab/pico_w/wifi/tls_client&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;study-swiftnio&#34;&gt;Study SwiftNIO&lt;/h2&gt;
&lt;p&gt;I&amp;rsquo;d like the API for my library to feel similar to how swift-nio-ssl works if the ergonomics are right for embedded. This assumes I&amp;rsquo;ll even get to that level of control for it. Which I probably won&amp;rsquo;t.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/apple/swift-nio-ssl&#34;&gt;https://github.com/apple/swift-nio-ssl&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/apple/swift-nio/blob/main/Sources/NIOTLS/&#34;&gt;https://github.com/apple/swift-nio/blob/main/Sources/NIOTLS/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;NOTE: An example Swift based &lt;a href=&#34;https://github.com/apple/swift-nio-examples/blob/main/TLSify/&#34;&gt;HTTP-&amp;gt;HTTPS proxy exits&lt;/a&gt; in the SwiftNIO examples repo if I decide to fall back from this problem.&lt;/p&gt;
&lt;h2 id=&#34;look-at-my-and-others-swift-http-clients&#34;&gt;Look at my (and other&amp;rsquo;s) Swift HTTP clients&lt;/h2&gt;
&lt;p&gt;This might be a good moment to revisit the actual client ergonomics.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/carlynorama/APItizer&#34;&gt;https://github.com/carlynorama/APItizer&lt;/a&gt; (No dependencies, older)&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://swiftonserver.com/building-swiftnio-clients/&#34;&gt;https://swiftonserver.com/building-swiftnio-clients/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/swift-server/async-http-client&#34;&gt;https://github.com/swift-server/async-http-client&lt;/a&gt; (async not available, but good to look at the ergonomics)&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://swiftpackageindex.com/search?query=HTTP+client&#34;&gt;https://swiftpackageindex.com/search?query=HTTP+client&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;look-at-some-api-packages--type-only-packages&#34;&gt;Look at some API packages / type-only packages&lt;/h2&gt;
&lt;p&gt;&lt;a href=&#34;https://github.com/apple/swift-log&#34;&gt;Swift Log&lt;/a&gt;, &lt;a href=&#34;https://github.com/apple/swift-metrics&#34;&gt;Swift Metrics&lt;/a&gt;, &lt;a href=&#34;https://github.com/apple/swift-distributed-tracing&#34;&gt;Swift Distributed Tracing&lt;/a&gt;, &lt;a href=&#34;https://github.com/apple/swift-configuration&#34;&gt;Swift Configure&lt;/a&gt; all are API definition and/or types only packages. I&amp;rsquo;d like my client to work similarly. I should spend some time looking at how these get laid out and used.&lt;/p&gt;
&lt;h2 id=&#34;choose-a-base-framework&#34;&gt;Choose a base framework&lt;/h2&gt;
&lt;p&gt;So &lt;a href=&#34;https://boringssl.googlesource.com/boringssl&#34;&gt;BoringSSL&lt;/a&gt;, which &lt;a href=&#34;https://github.com/apple/swift-nio-ssl/tree/main/Sources/CNIOBoringSSL&#34;&gt;swift-nio-ssl uses&lt;/a&gt;, isn&amp;rsquo;t a great fit for embedded.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ve got to say that mbed-tls is winning just because I know that espressif, pico and zephyr all use it. If I push the implementation down low enough then it doesn&amp;rsquo;t matter as much what future implementers want to use. Here are some links, but I think I&amp;rsquo;m already pretty focused on mbed-tls.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://mbed-tls.readthedocs.io/en/latest/&#34;&gt;https://mbed-tls.readthedocs.io/en/latest/&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/Mbed-TLS/mbedtls&#34;&gt;https://github.com/Mbed-TLS/mbedtls&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://docs.espressif.com/projects/esp-idf/en/latest/esp32c6/api-reference/protocols/mbedtls.html&#34;&gt;https://docs.espressif.com/projects/esp-idf/en/latest/esp32c6/api-reference/protocols/mbedtls.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://circuitlabs.net/https-with-tls-ssl-in-esp-idf/&#34;&gt;https://circuitlabs.net/https-with-tls-ssl-in-esp-idf/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://mongoose.ws/documentation/tutorials/tls/&#34;&gt;https://mongoose.ws/documentation/tutorials/tls/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://www.wolfssl.com&#34;&gt;https://www.wolfssl.com&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;summary&#34;&gt;Summary&lt;/h2&gt;
&lt;p&gt;This is just an orientation post. In the next couple I&amp;rsquo;ll get the hello worlds working without Swift, as a base goal. If it&amp;rsquo;s easy&amp;hellip; I&amp;rsquo;ll do more!&lt;/p&gt;
</description>
    </item>
    
    
    
    <item>
      <title>Why would I want a Hummingbird ChildRequestContext?</title>
      <link>https://whynotestflight.com/excuses/why-would-i-want-a-hummingbird-childrequestcontext/</link>
      <pubDate>Mon, 29 Sep 2025 00:00:00 +0000</pubDate>
      
      <guid>https://whynotestflight.com/excuses/why-would-i-want-a-hummingbird-childrequestcontext/</guid>
      <description>&lt;p&gt;&lt;a href=&#34;https://whynotestflight.com/excuses/so-what-even-is-a-hummingbird-requestcontext/&#34;&gt;Last post&lt;/a&gt; I made a &lt;a href=&#34;https://github.com/carlynorama/HummingbirdExamples/blob/main/08_context/customContext/Sources/customContext/Context/ForwardingRequestContext.swift&#34;&gt;ForwardingRequestContext&lt;/a&gt; and used it to save a value created by middleware.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ve got to admit it took me a minute to understand why and how to create a &lt;a href=&#34;https://docs.hummingbird.codes/2.0/documentation/hummingbird/childrequestcontext&#34;&gt;ChildRequestContext&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;First the how. I honestly ran in trouble the first time I tried to make one because I just assumed it was like sub-classing and just tried to jump in and make one with out really looking that hard at the documentation.  But it isn&amp;rsquo;t. The &amp;ldquo;Parent Context&amp;rdquo; is passed into the initializer as a concrete type that can be used to populate a new set of &lt;em&gt;child defined&lt;/em&gt; custom variables. The parent does, however, provide it&amp;rsquo;s copy of the &lt;a href=&#34;https://github.com/hummingbird-project/hummingbird/blob/main/Sources/Hummingbird/Server/RequestContext.swift&#34;&gt;fundamental storage&lt;/a&gt;. That parent &lt;em&gt;gets discarded&lt;/em&gt; after the initializer.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://github.com/search?q=repo%3Ahummingbird-project%2Fhummingbird-examples%20ChildRequestContext&amp;amp;type=code&#34;&gt;Most of the examples&lt;/a&gt; seem to have a &lt;a href=&#34;https://docs.swift.org/swift-book/documentation/the-swift-programming-language/initialization/&#34;&gt;throwing initializer&lt;/a&gt; for a child context. Throwing an error here can kick a client out of the app immediately.&lt;/p&gt;
&lt;p&gt;That throwing initializer pattern leads to an answer for WHY have a ChildRequestContext, controlling access to whole groups of api endpoint handlers based on conditions checked by middleware.&lt;/p&gt;
&lt;p&gt;To check that behavior out, I wrote &lt;a href=&#34;https://github.com/carlynorama/HummingbirdExamples/blob/main/08_context/customContext/Sources/customContext/Context/RCJunior.swift&#34;&gt;RCJunior&lt;/a&gt; to block access to certain routes if there&amp;rsquo;s no number in the URL to seed &lt;code&gt;timeConsumingData&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The code from this post and the last in a project: &lt;a href=&#34;https://github.com/carlynorama/HummingbirdExamples/tree/main/08_context/customContext&#34;&gt;https://github.com/carlynorama/HummingbirdExamples/tree/main/08_context/customContext&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&#34;what-is-the-call-going-to-look-like&#34;&gt;What is the call going to look like?&lt;/h2&gt;
&lt;p&gt;The &lt;a href=&#34;https://docs.hummingbird.codes/2.0/documentation/hummingbird/routergroup&#34;&gt;RouterGroup&lt;/a&gt; initializer provides the chance to insert the child context &lt;code&gt;Type&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;m going to show doing adding a &lt;a href=&#34;https://docs.hummingbird.codes/2.0/documentation/hummingbird/routergroup&#34;&gt;RouterGroup&lt;/a&gt; full written out rather than with &lt;a href=&#34;https://docs.hummingbird.codes/2.0/documentation/hummingbird/routerguide#Groups&#34;&gt;the common shorthand&lt;/a&gt; since I&amp;rsquo;ll be adding lots of comments.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//kiddiePoolRoutes will be of type RouterGroup&amp;lt;RCJunior&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;kiddiePoolRoutes&lt;/span&gt; = router.group(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;kiddiePool&amp;#34;&lt;/span&gt;, context: RCJunior.&lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;) 
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;a href=&#34;https://whynotestflight.com/excuses/how-about-catching-errors-with-hummingbird-middleware/#middleware-for-a-whole-route-block&#34;&gt;Like with middleware&lt;/a&gt;, the behavior instituted by the child context will only show up for defined api endpoints attached to the group (&lt;code&gt;kiddiePoolRoutes&lt;/code&gt;).&lt;/p&gt;
&lt;h2 id=&#34;the-child-requestcontext&#34;&gt;The Child RequestContext&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;RCJunior&lt;/code&gt; won&amp;rsquo;t conform to &lt;code&gt;ForwardingRequestContext&lt;/code&gt;, but will receive a &lt;code&gt;MyForwardingContext&lt;/code&gt; in the initializer to satisfy the &lt;a href=&#34;https://docs.hummingbird.codes/2.0/documentation/hummingbird/childrequestcontext/parentcontext&#34;&gt;&lt;code&gt;associatedtype ParentContext&lt;/code&gt;&lt;/a&gt; of a &lt;a href=&#34;https://docs.hummingbird.codes/2.0/documentation/hummingbird/childrequestcontext&#34;&gt;ChildRequestContext&lt;/a&gt;&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;Hummingbird&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;RCJunior&lt;/span&gt;: ChildRequestContext {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;coreContext&lt;/span&gt;: CoreRequestContextStorage
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;magicNumber&lt;/span&gt;: &lt;span style=&#34;color:#91d7e3&#34;&gt;Int&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//expects concrete type. &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;init&lt;/span&gt;(context parentContext: MyForwardingContext) &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;.coreContext = parentContext.coreContext
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;guard&lt;/span&gt; parentContext.timeConsumingData &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;!=&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;nil&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Status/418&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;throw&lt;/span&gt; HTTPError.&lt;span style=&#34;color:#ed8796&#34;&gt;init&lt;/span&gt;(.&lt;span style=&#34;color:#ed8796&#34;&gt;init&lt;/span&gt;(code: &lt;span style=&#34;color:#f5a97f&#34;&gt;418&lt;/span&gt;, reasonPhrase: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;I am a teapot.&amp;#34;&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;.magicNumber = parentContext.timeConsumingData!
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Unlike &lt;code&gt;timeConsumingData&lt;/code&gt;, &lt;code&gt;magicNumber&lt;/code&gt; isn&amp;rsquo;t an optional. If &lt;code&gt;timeConsumingData&lt;/code&gt; isn&amp;rsquo;t set in the parent this child context will fail to initialize. What does that mean? The context will halt progress and throw an error back up the middleware chain to be turned into the server&amp;rsquo;s response. All the middleware added to the router before the group gets declared will will run. None of the middleware added to the group will run.&lt;/p&gt;
&lt;p&gt;I picked an entertaining to me error message that means  &amp;ldquo;I&amp;rsquo;m a teapot. Find a coffee maker.&amp;rdquo; (&lt;a href=&#34;https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#418&#34;&gt;It&amp;rsquo;s an old code&amp;hellip;&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;A &lt;code&gt;ChildContextInfo&lt;/code&gt; would still have everything from the parent context&amp;rsquo;s storage, but none of it&amp;rsquo;s custom variables. Only it&amp;rsquo;s own.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;ChildContextInfo&lt;/span&gt;: ResponseEncodable {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;magicNumber&lt;/span&gt;: &lt;span style=&#34;color:#91d7e3&#34;&gt;Int&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;maxUploadSize&lt;/span&gt;: &lt;span style=&#34;color:#91d7e3&#34;&gt;Int&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;endpointPath&lt;/span&gt;: &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;?
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;parameters&lt;/span&gt;: &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;request_id&lt;/span&gt;: &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;decoder&lt;/span&gt;:&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;encoder&lt;/span&gt;:&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;logger&lt;/span&gt;:&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;an-api-endpoint-that-fails&#34;&gt;An api endpoint that fails&lt;/h3&gt;
&lt;p&gt;Adding an api endpoint that is not expected to work:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;kiddiePoolRoutes&lt;/span&gt; = router.group(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;kiddiePool&amp;#34;&lt;/span&gt;, context: RCJunior.&lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;) 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  kiddiePoolRoutes.&lt;span style=&#34;color:#c6a0f6&#34;&gt;get&lt;/span&gt; { &lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt;, context -&amp;gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;child route without &lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;number&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;CODE: &lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;context.magicNumber&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Call it&amp;hellip;&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;curl &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;-&lt;/span&gt;i &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;http://localhost:8080/kiddiePool&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;BONK!&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;HTTP/1.1 &lt;span style=&#34;color:#f5a97f&#34;&gt;418&lt;/span&gt; I&lt;span style=&#34;color:#ed8796&#34;&gt;&amp;#39;&lt;/span&gt;m a teapot
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Content-Length: &lt;span style=&#34;color:#f5a97f&#34;&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Date: Sun, &lt;span style=&#34;color:#f5a97f&#34;&gt;28&lt;/span&gt; Sep &lt;span style=&#34;color:#f5a97f&#34;&gt;2025&lt;/span&gt; 18:34:26 GMT
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Server: customContext
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;an-api-endpoint-that-works&#34;&gt;An api endpoint that works&lt;/h3&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  kiddiePoolRoutes.&lt;span style=&#34;color:#c6a0f6&#34;&gt;get&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;{number}&amp;#34;&lt;/span&gt;)  { &lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt;, context -&amp;gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;child route with &lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;number&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;CODE: &lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;context.magicNumber&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;curl -i &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;http://localhost:8080/kiddiePool/354&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;HTTP/1.1 &lt;span style=&#34;color:#f5a97f&#34;&gt;200&lt;/span&gt; OK
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Content-Type: text/plain; &lt;span style=&#34;color:#f4dbd6&#34;&gt;charset&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt;utf-8
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Content-Length: &lt;span style=&#34;color:#f5a97f&#34;&gt;9&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Date: Sun, &lt;span style=&#34;color:#f5a97f&#34;&gt;28&lt;/span&gt; Sep &lt;span style=&#34;color:#f5a97f&#34;&gt;2025&lt;/span&gt; 18:43:29 GMT
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Server: customContext
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;CODE: &lt;span style=&#34;color:#f5a97f&#34;&gt;366&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;other-api-endpoints-that-work&#34;&gt;Other api endpoints that work&lt;/h3&gt;
&lt;p&gt;Any route added to kiddiePool routes will have to have a &lt;code&gt;/{number}/&lt;/code&gt; in their path somewhere to have a chance of of working.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  kiddiePoolRoutes.&lt;span style=&#34;color:#c6a0f6&#34;&gt;get&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;/magic/{number}/**&amp;#34;&lt;/span&gt;)  { request, context -&amp;gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;description:&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;request.uri.description&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//catches the unnamed&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;parameters:&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;context.parameters.getCatchAll&lt;span style=&#34;color:#a6da95&#34;&gt;())&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;CODE: &lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;context.magicNumber&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;curl -i &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;http://localhost:8080/kiddiePool/magic/3/rabbit/saw/cards&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;HTTP/1.1 &lt;span style=&#34;color:#f5a97f&#34;&gt;200&lt;/span&gt; OK
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Content-Type: text/plain; &lt;span style=&#34;color:#f4dbd6&#34;&gt;charset&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt;utf-8
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Content-Length: &lt;span style=&#34;color:#f5a97f&#34;&gt;8&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Date: Sun, &lt;span style=&#34;color:#f5a97f&#34;&gt;28&lt;/span&gt; Sep &lt;span style=&#34;color:#f5a97f&#34;&gt;2025&lt;/span&gt; 18:59:31 GMT
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Server: customContext
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;CODE: &lt;span style=&#34;color:#f5a97f&#34;&gt;15&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The log reads:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## printed by first middleware before twoCents in second&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## it&amp;#39;s the result of number + userAgent.count &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f5a97f&#34;&gt;13&lt;/span&gt; is a big number! 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;description:/kiddiePool/magic/3/rabbit/saw/cards
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;parameters:&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;[&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;rabbit&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;saw&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;cards&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;dont-forget-to-test&#34;&gt;Don&amp;rsquo;t forget to test!&lt;/h2&gt;
&lt;p&gt;&lt;a href=&#34;https://github.com/carlynorama/HummingbirdExamples/blob/main/08_context/customContext/Tests/AppTests/AppTests.swift&#34;&gt;Tests&lt;/a&gt;&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;@Test &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;testKiddiePool&lt;/span&gt;() async &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;app&lt;/span&gt; = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; await buildApplication(TestArguments())
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//base, nothing else&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; await app.test(.router) { client &lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;_&lt;/span&gt; = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; await client.execute(uri: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;/kiddiePool/&amp;#34;&lt;/span&gt;, method: .&lt;span style=&#34;color:#c6a0f6&#34;&gt;get&lt;/span&gt;) { response &lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(response.status)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          #expect(response.status.code == &lt;span style=&#34;color:#f5a97f&#34;&gt;418&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//with number&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;number&lt;/span&gt; = &lt;span style=&#34;color:#f5a97f&#34;&gt;65&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; await app.test(.router) { client &lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;_&lt;/span&gt; = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; await client.execute(uri: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;/kiddiePool/&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;number&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;, method: .&lt;span style=&#34;color:#c6a0f6&#34;&gt;get&lt;/span&gt;) { response &lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          #expect(response.status == .ok)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;decoded&lt;/span&gt; = &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;(bytes: response.body.readableBytesView, encoding: .utf8 )
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//Hummingbird tests suite does not provide a User Agent.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;expectedTotal&lt;/span&gt; =  &lt;span style=&#34;color:#f5a97f&#34;&gt;2&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;+&lt;/span&gt;&lt;span style=&#34;color:#f5a97f&#34;&gt;732&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;+&lt;/span&gt;number
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          #expect(decoded == &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;CODE: &lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;expectedTotal&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//something in the path that is not a number&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; await app.test(.router) { client &lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;_&lt;/span&gt; = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; await client.execute(uri: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;/kiddiePool/notANumber&amp;#34;&lt;/span&gt;, method: .&lt;span style=&#34;color:#c6a0f6&#34;&gt;get&lt;/span&gt;) { response &lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(response.status)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          #expect(response.status.code == &lt;span style=&#34;color:#f5a97f&#34;&gt;418&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//undefined route&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; await app.test(.router) { client &lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;_&lt;/span&gt; = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; await client.execute(uri: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;/kiddiePool/notANumber/and/too/much/else&amp;#34;&lt;/span&gt;, method: .&lt;span style=&#34;color:#c6a0f6&#34;&gt;get&lt;/span&gt;) { response &lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(response.status)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          #expect(response.status == .notFound)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//magic path success&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;magicNumber&lt;/span&gt; = &lt;span style=&#34;color:#f5a97f&#34;&gt;3&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; await app.test(.router) { client &lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;_&lt;/span&gt; = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; await client.execute(uri: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;/kiddiePool/magic/&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;magicNumber&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;/rabbit/saw/cards&amp;#34;&lt;/span&gt;, method: .&lt;span style=&#34;color:#c6a0f6&#34;&gt;get&lt;/span&gt;) { response &lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(response.status)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          #expect(response.status == .ok)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;decoded&lt;/span&gt; = &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;(bytes: response.body.readableBytesView, encoding: .utf8 )
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          #expect(decoded &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;!=&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;nil&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;expectedTotal&lt;/span&gt; =  &lt;span style=&#34;color:#f5a97f&#34;&gt;2&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;+&lt;/span&gt;&lt;span style=&#34;color:#f5a97f&#34;&gt;732&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;+&lt;/span&gt;magicNumber
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          #expect(decoded == &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;CODE: &lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;expectedTotal&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//magic path no number&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; await app.test(.router) { client &lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;_&lt;/span&gt; = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; await client.execute(uri: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;/kiddiePool/magic/notANumber/rabbit/saw/cards&amp;#34;&lt;/span&gt;, method: .&lt;span style=&#34;color:#c6a0f6&#34;&gt;get&lt;/span&gt;) { response &lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(response.status)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          #expect(response.status.code == &lt;span style=&#34;color:#f5a97f&#34;&gt;418&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//magic path, number, but no followers&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//** requires something. &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; await app.test(.router) { client &lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;_&lt;/span&gt; = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; await client.execute(uri: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;/kiddiePool/magic/&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;magicNumber&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;/&amp;#34;&lt;/span&gt;, method: .&lt;span style=&#34;color:#c6a0f6&#34;&gt;get&lt;/span&gt;) { response &lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(response.status)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          #expect(response.status == .notFound)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;an-extra-note-on-middleware&#34;&gt;An extra note on Middleware&lt;/h2&gt;
&lt;p&gt;Something I was able to confirm while working on getting a child context right is that the order middleware gets added to a group matters, not just to the other middleware, but to the api endpoints as well.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;kiddiePoolRoutes&lt;/span&gt; = router.group(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;kiddiePool&amp;#34;&lt;/span&gt;, context: RCJunior.&lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;) 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//applies to everything after, so everything in &amp;#34;kiddiePoolRoutes&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  kiddiePoolRoutes.add(middleware: AlmostEmptyMiddleware(message: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;kiddiePool A&amp;#34;&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//curl -i &amp;#34;http://localhost:8080/kiddiePool/&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  kiddiePoolRoutes.&lt;span style=&#34;color:#c6a0f6&#34;&gt;get&lt;/span&gt; { &lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt;, context -&amp;gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;child route without &lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;number&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;CODE: &lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;context.magicNumber&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//curl -i &amp;#34;http://localhost:8080/kiddiePool/354&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  kiddiePoolRoutes.&lt;span style=&#34;color:#c6a0f6&#34;&gt;get&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;{number}&amp;#34;&lt;/span&gt;)  { &lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt;, context -&amp;gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;child route with &lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;number&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;CODE: &lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;context.magicNumber&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//this middleware will apply to &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//kiddiePoolRoutes.get(&amp;#34;/magic/{number}/**&amp;#34;) only. &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  kiddiePoolRoutes.add(middleware: AlmostEmptyMiddleware(message: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;kiddiePool B&amp;#34;&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//curl -i &amp;#34;http://localhost:8080/kiddiePool/magic/3/rabbit/saw/cards&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  kiddiePoolRoutes.&lt;span style=&#34;color:#c6a0f6&#34;&gt;get&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;/magic/{number}/**&amp;#34;&lt;/span&gt;)  { request, context -&amp;gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;description:&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;request.uri.description&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;parameters:&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;context.parameters.getCatchAll&lt;span style=&#34;color:#a6da95&#34;&gt;())&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;CODE: &lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;context.magicNumber&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;summary&#34;&gt;Summary&lt;/h2&gt;
&lt;p&gt;The &lt;code&gt;RCJunior&lt;/code&gt; ChildRequestContext uses an optional value in it&amp;rsquo;s ParentContext to determine if a client will get access to the API endpoints it applies to. Understanding this simple model will hopefully make it easier to sort through the workings of an actually-good auth library, &lt;a href=&#34;https://github.com/hummingbird-project/hummingbird-auth&#34;&gt;hummingbird-auth&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;That probably won&amp;rsquo;t be the next Hummingbird post, but it&amp;rsquo;s on the list.&lt;/p&gt;
</description>
    </item>
    
    
    
    <item>
      <title>So what even is a Hummingbird RequestContext?</title>
      <link>https://whynotestflight.com/excuses/so-what-even-is-a-hummingbird-requestcontext/</link>
      <pubDate>Sun, 28 Sep 2025 00:00:00 +0000</pubDate>
      
      <guid>https://whynotestflight.com/excuses/so-what-even-is-a-hummingbird-requestcontext/</guid>
      <description>&lt;p&gt;A RequestContext provides a companion data layer to the Hummingbird &lt;a href=&#34;https://github.com/hummingbird-project/hummingbird/blob/main/Sources/HummingbirdCore/Request/Request.swift&#34;&gt;Request&lt;/a&gt; type as it travels through the middleware to the api endpoint handler.&lt;/p&gt;
&lt;p&gt;A Hummingbird &lt;a href=&#34;https://github.com/hummingbird-project/hummingbird/blob/main/Sources/HummingbirdCore/Request/Request.swift&#34;&gt;Request&lt;/a&gt; largely echos the &lt;a href=&#34;https://github.com/apple/swift-http-types/blob/main/Sources/HTTPTypes/HTTPRequest.swift&#34;&gt;HTTPRequest&lt;/a&gt; type from &lt;a href=&#34;https://www.swift.org/blog/introducing-swift-http-types/&#34;&gt;HTTPTypes&lt;/a&gt;. If a given Hummingbird server wants to track different information that doesn&amp;rsquo;t normally get sent as part of the request, that&amp;rsquo;s a job for types conforming to the &lt;a href=&#34;https://docs.hummingbird.codes/2.0/documentation/hummingbird/requestcontexts/&#34;&gt;RequestContext&lt;/a&gt; protocol. &lt;em&gt;Some&lt;/em&gt; of the things I would have gone to &lt;a href=&#34;https://nginx.org/en/docs/example.html&#34;&gt;nginx&lt;/a&gt; or &lt;a href=&#34;https://httpd.apache.org/docs/2.4/mod/core.html#limitrequestbody&#34;&gt;apache&lt;/a&gt; configuration files for can end up handled by a combination of Middlewares and &lt;a href=&#34;https://swiftonserver.com/using-hummingbird-request-context/&#34;&gt;RequestContexts&lt;/a&gt; in Hummingbird. (Although many still live at the &lt;a href=&#34;https://docs.hummingbird.codes/2.0/documentation/hummingbird/serverprotocol&#34;&gt;Server level&lt;/a&gt;)&lt;/p&gt;
&lt;p&gt;Most basically, use a &lt;a href=&#34;https://docs.hummingbird.codes/2.0/documentation/hummingbird/requestcontext/&#34;&gt;RequestContext&lt;/a&gt; to override the default encoders/decoders and the maximum upload size. Key features of a context include how it can pull information up &lt;a href=&#34;https://docs.hummingbird.codes/2.0/documentation/hummingbird/requestcontexts/#Using-RequestContextSource&#34;&gt;from the server layer&lt;/a&gt; and how it can &lt;a href=&#34;https://docs.hummingbird.codes/2.0/documentation/hummingbird/requestcontexts/#Using-RequestContextSource&#34;&gt;work with Middleware&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The code in full project form (including the next post in progress) available at: &lt;a href=&#34;https://github.com/carlynorama/HummingbirdExamples/tree/main/08_context/customContext&#34;&gt;https://github.com/carlynorama/HummingbirdExamples/tree/main/08_context/customContext&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&#34;step-one-watch-a-message-get-passed&#34;&gt;Step One: watch a message get passed&lt;/h2&gt;
&lt;p&gt;First thing I wanted to do is watch how information flows (and doesn&amp;rsquo;t) via middleware and a RequestContext.&lt;/p&gt;
&lt;p&gt;All the RequestContext&amp;rsquo;s I&amp;rsquo;ve seen are structs, as is the &lt;a href=&#34;https://github.com/hummingbird-project/hummingbird/blob/9f422e0f79dbcc8613c891148076664f264a2625/Sources/Hummingbird/Server/RequestContext.swift#L43&#34;&gt;RequestContextStorage&lt;/a&gt;. Information held in a context can only get passed DOWN the Middleware stack and into to the api endpoint handler. Nothing comes back up with the Response. I haven&amp;rsquo;t done any reading or experiments on storing a reference type &lt;em&gt;inside&lt;/em&gt; a RequestContext, which could be an interesting thing to try.&lt;/p&gt;
&lt;h3 id=&#34;the-context&#34;&gt;The Context&lt;/h3&gt;
&lt;p&gt;I wrote both a custom RequestContext and a matching protocol to needed craft the middleware.&lt;/p&gt;
&lt;p&gt;NOTE: When writing a middleware to be shared as a library, that protocol will be more important than the concrete type so developers can implement their own Contexts that support all the various Middlewares they need.&lt;/p&gt;
&lt;p&gt;There&amp;rsquo;s only one special item: a &lt;code&gt;noteToPass&lt;/code&gt; string.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;Hummingbird&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;protocol&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;ForwardingRequestContext&lt;/span&gt;: RequestContext {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;noteToPass&lt;/span&gt;: &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;?  { &lt;span style=&#34;color:#c6a0f6&#34;&gt;get&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;set&lt;/span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;MyForwardingContext&lt;/span&gt;: ForwardingRequestContext {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//protocol requirement&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;coreContext&lt;/span&gt;: CoreRequestContextStorage 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;noteToPass&lt;/span&gt;: &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;?
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;init&lt;/span&gt;(source: Source) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;.coreContext = .&lt;span style=&#34;color:#ed8796&#34;&gt;init&lt;/span&gt;(source: source)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;.noteToPass = &lt;span style=&#34;color:#f5a97f&#34;&gt;nil&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;the-sending-middleware&#34;&gt;The Sending Middleware&lt;/h3&gt;
&lt;p&gt;The &amp;ldquo;sending&amp;rdquo; middleware will be the middleware first listed in the stack. It gets it&amp;rsquo;s hands on the context first. In this case the middleware needs a promise that the context will have a &lt;code&gt;noteToPass&lt;/code&gt; variable, which gets done by providing the &lt;code&gt;ForwardingRequestContext&lt;/code&gt; just made, rather than the more generic &lt;code&gt;RequestContext&lt;/code&gt; as required by the &lt;a href=&#34;https://github.com/hummingbird-project/hummingbird/blob/9f422e0f79dbcc8613c891148076664f264a2625/Sources/Hummingbird/Middleware/Middleware.swift#L53&#34;&gt;RouterMiddleware protocol&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;handle&lt;/code&gt; function needs its own &lt;code&gt;var&lt;/code&gt; copy of the context to make any changes since the parameter comes in as a let.&lt;/p&gt;
&lt;p&gt;Nothing done to the context after the call to &lt;code&gt;next&lt;/code&gt; matters to subsequent middleware or the ultimate api endpoint handler.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;Hummingbird&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;SendingMiddleware&lt;/span&gt;&amp;lt;Context: ForwardingRequestContext&amp;gt;: RouterMiddleware {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;handle&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; request: Request, context: Context, next: (Request, Context) async &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; -&amp;gt; Response) async &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; -&amp;gt; Response {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;sending...&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;contextToPassForward&lt;/span&gt; = context
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        contextToPassForward.noteToPass = &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Howdy future Middleware!&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;response&lt;/span&gt; = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; await next(request, contextToPassForward)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// DON&amp;#39;T TRY TO DO ANYTHING TO A CONTEXT HERE.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// IT DOESN&amp;#39;T GO BACK &amp;#34;UP&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; response
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;receiving-middleware&#34;&gt;Receiving Middleware&lt;/h3&gt;
&lt;p&gt;I called this the &amp;ldquo;Receiving&amp;rdquo; middleware, but the &lt;code&gt;noteToPass&lt;/code&gt; isn&amp;rsquo;t private. Any middleware can open it up along the way.&lt;/p&gt;
&lt;p&gt;In the &lt;a href=&#34;https://github.com/carlynorama/HummingbirdExamples/blob/main/08_context/customContext/Sources/customContext/Application%2Bbuild.swift&#34;&gt;example code&lt;/a&gt; this will be the last middleware to touch the context before it goes into the final api endpoint handler. Here it swaps in it&amp;rsquo;s own text for the note.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;Hummingbird&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;ReceivingMiddleware&lt;/span&gt;&amp;lt;Context: ForwardingRequestContext&amp;gt;: RouterMiddleware {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;handle&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; request: Request, context: Context, next: (Request, Context) async &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; -&amp;gt; Response) async &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; -&amp;gt; Response {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;receiving...&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;contextToPass&lt;/span&gt; = context
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Receiver got: &lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;context.noteToPass ?? &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;no message from sender&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        contextToPass.noteToPass = &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Receiver says hi too!&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; await next(request, contextToPass)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;back-in-applicationbuild&#34;&gt;Back in Application+build&lt;/h3&gt;
&lt;p&gt;Since most of the examples have been following the Hummingbird suggested model of setting a Typealias for the context it&amp;rsquo;s super easy to swap in the new custom context up at the top-ish of &lt;code&gt;Application+build.swift&lt;/code&gt;&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//Set alias to custom RequestContext&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;typealias&lt;/span&gt; AppRequestContext = MyForwardingContext
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;These new middlewares get added with the sender on top:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  router.addMiddleware {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    SendingMiddleware()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    LogRequestsMiddleware(.info)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    ReceivingMiddleware()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;But I also want to see everything that my context knows about the world when it hits the api endpoint handler. I made a type that combines my custom value with the values in the protocol required &lt;a href=&#34;https://github.com/hummingbird-project/hummingbird/blob/9f422e0f79dbcc8613c891148076664f264a2625/Sources/Hummingbird/Server/RequestContext.swift#L43&#34;&gt;RequestContextStorage&lt;/a&gt;, which itself points to other sources:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/hummingbird-project/hummingbird/blob/9f422e0f79dbcc8613c891148076664f264a2625/Sources/Hummingbird/Server/RequestContextSource.swift#L19&#34;&gt;RequestContextSource&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/hummingbird-project/hummingbird/blob/9f422e0f79dbcc8613c891148076664f264a2625/Sources/Hummingbird/Server/RequestContext.swift#L43&#34;&gt;CoreRequestContextStorage&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/hummingbird-project/hummingbird-docs/blob/795f2e84e5817aabbd120e6f3246329662508497/Hummingbird.docc/Articles/RequestContexts.md?plain=1#L103&#34;&gt;AppRequestContext&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;ContextInfo&lt;/span&gt;: ResponseEncodable {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;noteToPass&lt;/span&gt;: &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;? &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//custom context&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;maxUploadSize&lt;/span&gt;: &lt;span style=&#34;color:#91d7e3&#34;&gt;Int&lt;/span&gt; &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//RequestContext extension &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;endpointPath&lt;/span&gt;: &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;? &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//from CoreRequestContextStorage&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;parameters&lt;/span&gt;: &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt; &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//from CoreRequestContextStorage&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;request_id&lt;/span&gt;: &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;  &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//from Logger in RequestContextSource&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;decoder&lt;/span&gt;:&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt; &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//RequestContext associated type default&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;encoder&lt;/span&gt;:&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt; &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//RequestContext associated type default&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;logger&lt;/span&gt;:&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt; &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//from RequestContextSource protocol&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Not shown is the &lt;code&gt;context.channel&lt;/code&gt; which is available &lt;a href=&#34;https://github.com/hummingbird-project/hummingbird/blob/9f422e0f79dbcc8613c891148076664f264a2625/Sources/Hummingbird/Server/RequestContextSource.swift#L25C15-L25C46&#34;&gt;to the application layer&lt;/a&gt;, see the &lt;a href=&#34;https://docs.hummingbird.codes/2.0/documentation/hummingbird/requestcontexts#Using-RequestContextSource&#34;&gt;IP passing&lt;/a&gt; example in the docs for how to get access to it in your own code.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  router.&lt;span style=&#34;color:#c6a0f6&#34;&gt;get&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;contextSpy&amp;#34;&lt;/span&gt;) { &lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt;, context -&amp;gt; ContextInfo &lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    ContextInfo(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      noteToPass: context.noteToPass,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      maxUploadSize: context.maxUploadSize,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      endpointPath: context.endpointPath,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      parameters: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;context.parameters&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      request_id: context.id,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      decoder: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;context.requestDecoder&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      encoder: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;context.responseEncoder&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      logger: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;context.logger&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      )
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Running the server and making the call&amp;hellip;&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; curl -i &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;http://localhost:8080/contextSpy&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-json&#34; data-lang=&#34;json&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;HTTP/&lt;/span&gt;&lt;span style=&#34;color:#f5a97f&#34;&gt;1.1&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;200&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;OK&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;Content-Type:&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;application/json;&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;charset=utf&lt;/span&gt;&lt;span style=&#34;color:#f5a97f&#34;&gt;-8&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;Content-Length:&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;290&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;Date:&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;Sun,&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;28&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;Sep&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;2025&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;14&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#f5a97f&#34;&gt;05&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#f5a97f&#34;&gt;22&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;GMT&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;Server:&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;customContext&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{&lt;span style=&#34;color:#c6a0f6&#34;&gt;&amp;#34;parameters&amp;#34;&lt;/span&gt;:&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;FlatDictionary&amp;lt;Substring, Substring&amp;gt;(elements: [], hashKeys: [])&amp;#34;&lt;/span&gt;,&lt;span style=&#34;color:#c6a0f6&#34;&gt;&amp;#34;logger&amp;#34;&lt;/span&gt;:&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Logger(_storage: Logging.Logger.Storage)&amp;#34;&lt;/span&gt;,&lt;span style=&#34;color:#c6a0f6&#34;&gt;&amp;#34;decoder&amp;#34;&lt;/span&gt;:&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Foundation.JSONDecoder&amp;#34;&lt;/span&gt;,&lt;span style=&#34;color:#c6a0f6&#34;&gt;&amp;#34;endpointPath&amp;#34;&lt;/span&gt;:&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;\/contextSpy&amp;#34;&lt;/span&gt;,&lt;span style=&#34;color:#c6a0f6&#34;&gt;&amp;#34;noteToPass&amp;#34;&lt;/span&gt;:&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Receiver says hi too!&amp;#34;&lt;/span&gt;,&lt;span style=&#34;color:#c6a0f6&#34;&gt;&amp;#34;encoder&amp;#34;&lt;/span&gt;:&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Foundation.JSONEncoder&amp;#34;&lt;/span&gt;,&lt;span style=&#34;color:#c6a0f6&#34;&gt;&amp;#34;maxUploadSize&amp;#34;&lt;/span&gt;:&lt;span style=&#34;color:#f5a97f&#34;&gt;2097152&lt;/span&gt;,&lt;span style=&#34;color:#c6a0f6&#34;&gt;&amp;#34;request_id&amp;#34;&lt;/span&gt;:&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;53075b9f900ce1b32da2fb96a5c10332&amp;#34;&lt;/span&gt;} 
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The output contains the receiver&amp;rsquo;s version&amp;rsquo;s of the note.&lt;/p&gt;
&lt;h2 id=&#34;read-a-route-parameter&#34;&gt;Read A Route Parameter&lt;/h2&gt;
&lt;p&gt;What&amp;rsquo;s also notable in the output above is the empty parameters dictionary. That&amp;rsquo;s for storing any information Hummingbird extracted from route variables. Let&amp;rsquo;s revise the context to store a manipulated value based on an &lt;code&gt;Integer&lt;/code&gt; value passed in via the route.&lt;/p&gt;
&lt;p&gt;First to put the var in the RequestContext:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;Hummingbird&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;protocol&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;ForwardingRequestContext&lt;/span&gt;: RequestContext {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;noteToPass&lt;/span&gt;: &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;? { &lt;span style=&#34;color:#c6a0f6&#34;&gt;get&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;set&lt;/span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;timeConsumingData&lt;/span&gt;: &lt;span style=&#34;color:#91d7e3&#34;&gt;Int&lt;/span&gt;? { &lt;span style=&#34;color:#c6a0f6&#34;&gt;get&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;set&lt;/span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;MyForwardingContext&lt;/span&gt;: ForwardingRequestContext {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#ed8796&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;coreContext&lt;/span&gt;: CoreRequestContextStorage
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#ed8796&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;noteToPass&lt;/span&gt;: &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;?
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#ed8796&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;timeConsumingData&lt;/span&gt;: &lt;span style=&#34;color:#91d7e3&#34;&gt;Int&lt;/span&gt;?
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#ed8796&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;init&lt;/span&gt;(source: Source) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;.coreContext = .&lt;span style=&#34;color:#ed8796&#34;&gt;init&lt;/span&gt;(source: source)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;.noteToPass = &lt;span style=&#34;color:#f5a97f&#34;&gt;nil&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;.timeConsumingData = &lt;span style=&#34;color:#f5a97f&#34;&gt;nil&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;new-sending-middleware&#34;&gt;New Sending Middleware&lt;/h3&gt;
&lt;p&gt;The new sending middleware will conditionally update &lt;code&gt;timeConsumingData&lt;/code&gt; based on an &amp;ldquo;algorithm&amp;rdquo; that combines the potential number in the url with information from the request.&lt;/p&gt;
&lt;p&gt;I called it &lt;code&gt;timeConsumingProcess&lt;/code&gt; to emphasize why creating a middleware that&amp;rsquo;s context dependant might have value. It might seem easier to keep middlewares self reliant, but every repeat process gets repeated for EVERY request that the middleware will touch. That&amp;rsquo;s a lot of extra work.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;Hummingbird&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;SendingMiddleware&lt;/span&gt;&amp;lt;Context: ForwardingRequestContext&amp;gt;: RouterMiddleware {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;handle&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; request: Request, context: Context, next: (Request, Context) async &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; -&amp;gt; Response) async &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; -&amp;gt; Response {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;sending...&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;contextToPassForward&lt;/span&gt; = context
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        contextToPassForward.noteToPass = &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Howdy future Middleware!&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;pathNumber&lt;/span&gt; = &lt;span style=&#34;color:#91d7e3&#34;&gt;Int&lt;/span&gt;(context.parameters.&lt;span style=&#34;color:#c6a0f6&#34;&gt;get&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;number&amp;#34;&lt;/span&gt;) ?? &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;nope.&amp;#34;&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;requestNumber&lt;/span&gt; = timeConsumingRequestProcessingTask(on: request)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            contextToPassForward.timeConsumingData = pathNumber &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;+&lt;/span&gt; requestNumber
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;response&lt;/span&gt; = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; await next(request, contextToPassForward)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; response
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;private&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;timeConsumingRequestProcessingTask&lt;/span&gt;(on request:Request) -&amp;gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;Int&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;agent&lt;/span&gt; = request.headers[.userAgent] {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;agent&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt; wants to play. &lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;agent.&lt;span style=&#34;color:#91d7e3&#34;&gt;count&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; agent.&lt;span style=&#34;color:#91d7e3&#34;&gt;count&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;732&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;new-receiving&#34;&gt;New Receiving&lt;/h3&gt;
&lt;p&gt;The receiver will check to see if the value in the context has been previously set, and if so add&amp;hellip; it&amp;rsquo;s 2¢.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;Hummingbird&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;ReceivingMiddleware&lt;/span&gt;&amp;lt;Context: ForwardingRequestContext&amp;gt;: RouterMiddleware {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;handle&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; request: Request, context: Context, next: (Request, Context) async &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; -&amp;gt; Response) async &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; -&amp;gt; Response {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;receiving...&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;contextToPass&lt;/span&gt; = context
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Receiver got: &lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;context.noteToPass ?? &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;no message from sender&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        contextToPass.noteToPass = &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Receiver says hi too!&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; context.timeConsumingData &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;!=&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;nil&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            contextToPass.timeConsumingData = myTwoCents(number: context.timeConsumingData!)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; await next(request, contextToPass)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;private&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;myTwoCents&lt;/span&gt;(number: &lt;span style=&#34;color:#91d7e3&#34;&gt;Int&lt;/span&gt;) -&amp;gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;Int&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;number&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt; is a big number!&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; number &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;+&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;2&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;new-endpoint&#34;&gt;New Endpoint&lt;/h3&gt;
&lt;p&gt;Adding the value to the ContextInfo structure&amp;hellip;&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;ContextInfo&lt;/span&gt;: ResponseEncodable {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;timeConsumingData&lt;/span&gt;: &lt;span style=&#34;color:#91d7e3&#34;&gt;Int&lt;/span&gt;?
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;noteToPass&lt;/span&gt;: &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;?
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;maxUploadSize&lt;/span&gt;: &lt;span style=&#34;color:#91d7e3&#34;&gt;Int&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;endpointPath&lt;/span&gt;: &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;?
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;parameters&lt;/span&gt;: &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;request_id&lt;/span&gt;: &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;decoder&lt;/span&gt;:&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;encoder&lt;/span&gt;:&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;logger&lt;/span&gt;:&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And creating and endpoint that expects a value:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//http://localhost:8080/contextSpy/anythingHere&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//&amp;#34;parameters&amp;#34;: ... elements: [(key: \&amp;#34;number\&amp;#34;, value: \&amp;#34;anythingHere\&amp;#34;)] ...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  router.&lt;span style=&#34;color:#c6a0f6&#34;&gt;get&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;contextSpy/{number}&amp;#34;&lt;/span&gt;) { &lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt;, context -&amp;gt; ContextInfo &lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    ContextInfo(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      timeConsumingData: context.timeConsumingData,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      noteToPass: context.noteToPass,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      maxUploadSize: context.maxUploadSize,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      endpointPath: context.endpointPath,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      parameters: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;context.parameters&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      request_id: context.id,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      decoder: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;context.requestDecoder&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      encoder: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;context.responseEncoder&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      logger: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;context.logger&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      )
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;NOTE: The old endpoint will need updating, too. When it&amp;rsquo;s called the JSON just won&amp;rsquo;t have a &amp;ldquo;timeConsumingData&amp;rdquo; value and the parameters will still be empty.&lt;/p&gt;
&lt;p&gt;Seeing the result:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;curl -i &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;http://localhost:8080/contextSpy/354&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-json&#34; data-lang=&#34;json&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;HTTP/&lt;/span&gt;&lt;span style=&#34;color:#f5a97f&#34;&gt;1.1&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;200&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;OK&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;Content-Type:&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;application/json;&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;charset=utf&lt;/span&gt;&lt;span style=&#34;color:#f5a97f&#34;&gt;-8&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;Content-Length:&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;377&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;Date:&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;Sun,&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;28&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;Sep&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;2025&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;14&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#f5a97f&#34;&gt;26&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#f5a97f&#34;&gt;33&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;GMT&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;Server:&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;customContext&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{&lt;span style=&#34;color:#c6a0f6&#34;&gt;&amp;#34;maxUploadSize&amp;#34;&lt;/span&gt;:&lt;span style=&#34;color:#f5a97f&#34;&gt;2097152&lt;/span&gt;,&lt;span style=&#34;color:#c6a0f6&#34;&gt;&amp;#34;timeConsumingData&amp;#34;&lt;/span&gt;:&lt;span style=&#34;color:#f5a97f&#34;&gt;366&lt;/span&gt;,&lt;span style=&#34;color:#c6a0f6&#34;&gt;&amp;#34;noteToPass&amp;#34;&lt;/span&gt;:&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Receiver says hi too!&amp;#34;&lt;/span&gt;,&lt;span style=&#34;color:#c6a0f6&#34;&gt;&amp;#34;endpointPath&amp;#34;&lt;/span&gt;:&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;\/contextSpy\/{number}&amp;#34;&lt;/span&gt;,&lt;span style=&#34;color:#c6a0f6&#34;&gt;&amp;#34;decoder&amp;#34;&lt;/span&gt;:&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Foundation.JSONDecoder&amp;#34;&lt;/span&gt;,&lt;span style=&#34;color:#c6a0f6&#34;&gt;&amp;#34;request_id&amp;#34;&lt;/span&gt;:&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;53075b9f900ce1b32da2fb96a5c10331&amp;#34;&lt;/span&gt;,&lt;span style=&#34;color:#c6a0f6&#34;&gt;&amp;#34;encoder&amp;#34;&lt;/span&gt;:&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Foundation.JSONEncoder&amp;#34;&lt;/span&gt;,&lt;span style=&#34;color:#c6a0f6&#34;&gt;&amp;#34;logger&amp;#34;&lt;/span&gt;:&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Logger(_storage: Logging.Logger.Storage)&amp;#34;&lt;/span&gt;,&lt;span style=&#34;color:#c6a0f6&#34;&gt;&amp;#34;parameters&amp;#34;&lt;/span&gt;:&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;FlatDictionary&amp;lt;Substring, Substring&amp;gt;(elements: [(key: \&amp;#34;number\&amp;#34;, value: \&amp;#34;354\&amp;#34;)], hashKeys: [5772982973116696044])&amp;#34;&lt;/span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;We have a parameter!&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;FlatDictionary&amp;lt;Substring, Substring&amp;gt;(elements: [(key: \&amp;#34;number\&amp;#34;, value: \&amp;#34;354\&amp;#34;)], hashKeys: [-6711111692066375814])&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This parameters array stores route based values only. Code meant to handle a query encoded request like:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;curl -i &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;http://localhost:8080/urlQueryCheck?x=45&amp;amp;y=33&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;will accesses the values via the Request:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;request.uri.queryParameters
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;summary&#34;&gt;Summary&lt;/h2&gt;
&lt;p&gt;The RequestContext / Middleware pair can accomplish some pretty powerful work.  That power can be sharpened by narrowing down into a &lt;a href=&#34;https://docs.hummingbird.codes/2.0/documentation/hummingbird/childrequestcontext&#34;&gt;ChildRequestContext&lt;/a&gt; for a &lt;a href=&#34;https://docs.hummingbird.codes/2.0/documentation/hummingbird/routergroup&#34;&gt;RouteGroup&lt;/a&gt; once certain requirements have been met.&lt;/p&gt;
&lt;p&gt;That&amp;rsquo;s the next post!&lt;/p&gt;
</description>
    </item>
    
    
    
    <item>
      <title>(changing a terminal prompt)</title>
      <link>https://whynotestflight.com/excuses/changing-a-terminal-prompt/</link>
      <pubDate>Sat, 27 Sep 2025 00:00:00 +0000</pubDate>
      
      <guid>https://whynotestflight.com/excuses/changing-a-terminal-prompt/</guid>
      <description>&lt;p&gt;So name and directory aren&amp;rsquo;t in the &amp;ldquo;shot&amp;rdquo;, where &lt;code&gt;$&amp;gt;&lt;/code&gt; is the desired prompt.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## set the prompt for just that window&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#91d7e3&#34;&gt;export&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;PS1&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;$&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;gt; &amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## clear the window&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;reset
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://askubuntu.com/questions/25077/how-to-really-clear-the-terminal&#34;&gt;https://askubuntu.com/questions/25077/how-to-really-clear-the-terminal&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://unix.stackexchange.com/questions/386404/how-to-change-the-format-of-the-bash-prompt&#34;&gt;https://unix.stackexchange.com/questions/386404/how-to-change-the-format-of-the-bash-prompt&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</description>
    </item>
    
    
    
    <item>
      <title>How about catching errors with Hummingbird Middleware?</title>
      <link>https://whynotestflight.com/excuses/how-about-catching-errors-with-hummingbird-middleware/</link>
      <pubDate>Sat, 27 Sep 2025 00:00:00 +0000</pubDate>
      
      <guid>https://whynotestflight.com/excuses/how-about-catching-errors-with-hummingbird-middleware/</guid>
      <description>&lt;p&gt;This article will show four different error responses based on Middleware:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;how to &lt;a href=&#34;#log-errors-middleware&#34;&gt;print them to the log&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;how to &lt;a href=&#34;#return-static-page&#34;&gt;return a static HTML based 404 page&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;how to return &lt;a href=&#34;#return-dynamic-page&#34;&gt;dynamic HTML in response to any error&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;how to choose to &lt;a href=&#34;#return-json&#34;&gt;send JSON instead&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;These can all be seen in &lt;a href=&#34;https://github.com/carlynorama/HummingbirdExamples/tree/main/07_middleware&#34;&gt;the repo&lt;/a&gt; along with the examples from the last post.&lt;/p&gt;
&lt;p&gt;Order matters in a Middleware stack. All of these examples work by catching the errors relevant to their tasks and returning a &lt;code&gt;Response&lt;/code&gt;. Changing a &lt;code&gt;HTTPError&lt;/code&gt; with a 404 status into a &lt;code&gt;Response&lt;/code&gt; with a 404 status means that middleware which is only looking for unhandled errors will not &lt;code&gt;catch&lt;/code&gt; an already packaged &lt;code&gt;Response&lt;/code&gt;! This is a feature because it let&amp;rsquo;s the developer progressively filter out errors when requests or the errors meet certain conditions, like in the &lt;a href=&#34;#return-json&#34;&gt;JSON example&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;It&amp;rsquo;s also good to note what a not-found Middleware can&amp;rsquo;t do using the trie router, which is to apply to a whole branch of routes selectively. For groups and collections the trie router applies middleware to the found routes only, but there is a way around that &lt;a href=&#34;#middleware-for-a-whole-route-block&#34;&gt;discussed at the end&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;log-errors-middleware&#34;&gt;Log Errors Middleware&lt;/h2&gt;
&lt;p&gt;It&amp;rsquo;s not just &lt;code&gt;Responses&lt;/code&gt; that percolate up through middleware, but errors too. From what I can tell most if not all errors thrown by Hummingbird itself will be an &lt;a href=&#34;https://github.com/hummingbird-project/hummingbird/blob/main/Sources/Hummingbird/Error/HTTPError.swift&#34;&gt;HTTPError&lt;/a&gt; (&lt;a href=&#34;https://docs.hummingbird.codes/2.0/documentation/hummingbird/errorhandling&#34;&gt;docs&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;To get a sense of what&amp;rsquo;s happening &lt;code&gt;LogErrorsMiddleware&lt;/code&gt; will print out the errors it encounters to the Log. In projects with a lot of middleware, moving &lt;code&gt;LogErrorsMiddleware&lt;/code&gt;&amp;rsquo;s placement around the stack operates much like moving a stethoscope around, triangulating a problem.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;Hummingbird&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;Logging&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;LogErrorsMiddleware&lt;/span&gt;&amp;lt;Context: RequestContext&amp;gt;: RouterMiddleware {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;level&lt;/span&gt;:Logger.Level
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;formatHeaderForLog&lt;/span&gt;(headers: HTTPFields) -&amp;gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;forLog&lt;/span&gt; = &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;for&lt;/span&gt; header &lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt; headers {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            forLog.append(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\t&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;header.name&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;header.value&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\n&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        forLog.append(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;------&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; forLog
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;handle&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; request: Request, context: Context, next: (Request, Context) async &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; -&amp;gt; Response) async &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; -&amp;gt; Response {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;do&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; await next(request, context)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        } &lt;span style=&#34;color:#c6a0f6&#34;&gt;catch&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;error&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;as&lt;/span&gt; HTTPError {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;status&lt;/span&gt; = error.status
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;formattedHeaders&lt;/span&gt; = formatHeaderForLog(headers: error.headers)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            context.logger.log(level: level, Logger.Message(stringLiteral: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\n&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;Responding&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;status&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt; with:&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\n&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;formattedHeaders&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;throw&lt;/span&gt; error
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;It&amp;rsquo;s output looks like:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;025-09-27T04:10:53-0700 info inthemiddle: hb.request.id&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt;7c21d9a8dea288aed30d15e3536012ea &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;[&lt;/span&gt;inthemiddle&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;]&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Responding &lt;span style=&#34;color:#f5a97f&#34;&gt;404&lt;/span&gt; Not Found to /other/ call:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;------
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;There are no headers yet. The curl output shows a handful added at the last moment.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## curl -i &amp;#34;http://localhost:8080/other/&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;HTTP/1.1 &lt;span style=&#34;color:#f5a97f&#34;&gt;404&lt;/span&gt; Not Found
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Content-Length: &lt;span style=&#34;color:#f5a97f&#34;&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Date: Sat, &lt;span style=&#34;color:#f5a97f&#34;&gt;27&lt;/span&gt; Sep &lt;span style=&#34;color:#f5a97f&#34;&gt;2025&lt;/span&gt; 11:10:52 GMT
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Server: inthemiddle
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;These do not appear to be added by the &lt;a href=&#34;https://github.com/hummingbird-project/hummingbird/blob/9f422e0f79dbcc8613c891148076664f264a2625/Sources/Hummingbird/Router/ResponseGenerator.swift#L134&#34;&gt;defaultHummingbirdHeaders&lt;/a&gt; method called by the &lt;a href=&#34;https://github.com/hummingbird-project/hummingbird/blob/9f422e0f79dbcc8613c891148076664f264a2625/Sources/Hummingbird/Codable/JSON/JSONCoding.swift#L32&#34;&gt;default JSONEncoder&lt;/a&gt;, but instead added at the Application layer.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;server name: &lt;a href=&#34;https://github.com/hummingbird-project/hummingbird/blob/9f422e0f79dbcc8613c891148076664f264a2625/Sources/Hummingbird/Application.swift#L132&#34;&gt;Application.swift#L132&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;content length: &lt;a href=&#34;https://github.com/hummingbird-project/hummingbird/blob/9f422e0f79dbcc8613c891148076664f264a2625/Sources/HummingbirdCore/Response/Response.swift#L37&#34;&gt;Response.swift#L37&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;date: &lt;a href=&#34;https://github.com/hummingbird-project/hummingbird/blob/9f422e0f79dbcc8613c891148076664f264a2625/Sources/Hummingbird/Application.swift#L129&#34;&gt;Application.swift#L129&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I found these lines by searching the Hummingbird repo for the &lt;code&gt;.headerName&lt;/code&gt; as determined by the &lt;a href=&#34;https://github.com/apple/swift-http-types/blob/97c96755ae30dd9a7c594c830a3334986cc0e25a/Sources/HTTPTypes/HTTPFieldName.swift#L333&#34;&gt;HTTPField names&lt;/a&gt; of the &lt;a href=&#34;https://github.com/apple/swift-http-types/&#34;&gt;HTTPTypes&lt;/a&gt; package.&lt;/p&gt;
&lt;h2 id=&#34;return-static-page&#34;&gt;Return Static Page&lt;/h2&gt;
&lt;p&gt;The original itch to explore middleware came from wanting to get a better &amp;ldquo;Not Found&amp;rdquo; error, just a classic 404 page. Hummingbird formulates an &lt;code&gt;HTTPError&lt;/code&gt; for this situation in the &lt;a href=&#34;https://github.com/hummingbird-project/hummingbird/blob/9f422e0f79dbcc8613c891148076664f264a2625/Sources/Hummingbird/Router/RouterResponder.swift#L44&#34;&gt;&lt;code&gt;respond&lt;/code&gt; method&lt;/a&gt; using the &lt;a href=&#34;https://github.com/hummingbird-project/hummingbird/blob/9f422e0f79dbcc8613c891148076664f264a2625/Sources/Hummingbird/Router/RouterResponder.swift#L56&#34;&gt;notFoundResponder&lt;/a&gt; belonging to the &lt;a href=&#34;https://github.com/hummingbird-project/hummingbird/blob/main/Sources/Hummingbird/Router/RouterResponder.swift&#34;&gt;&lt;code&gt;RouterResponder&lt;/code&gt;&lt;/a&gt; which the application builds from the &lt;code&gt;Router&lt;/code&gt; passed to it at startup.&lt;/p&gt;
&lt;p&gt;This handler performs it&amp;rsquo;s task classically by using &lt;a href=&#34;https://docs.hummingbird.codes/2.0/documentation/hummingbirdcore/response/redirecttype&#34;&gt;a redirect&lt;/a&gt;. It uses the &lt;a href=&#34;https://en.wikipedia.org/wiki/HTTP_303&#34;&gt;303 (see other)&lt;/a&gt; redirect, telling the browser that trying this page again in the future might get a different response, or maybe not. As such, a client should never cache it.&lt;/p&gt;
&lt;p&gt;More &lt;a href=&#34;https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#3xx_redirection&#34;&gt;on redirects&lt;/a&gt; and &lt;a href=&#34;https://datatracker.ietf.org/doc/html/rfc7234#section-4.2.2&#34;&gt;caching them&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;Static404Middleware&lt;/code&gt; ONLY redirects 404 errors, leaving everything else alone.  Since middleware higher up catches requests before the lower ones, but responses after, placing &lt;code&gt;Static404Middleware&lt;/code&gt; below the logger will catch 404&amp;rsquo;s before the logger has a chance to register them.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  router.addMiddleware {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//built in logger.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    LogRequestsMiddleware(.info)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//custom middleware for logging errors&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//will never log 404&amp;#39;s because Static404Middleware&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//catches them first. &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    LogErrorsMiddleware(level: .info)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//Serves static 404 pages&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    Static404Middleware()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    FileMiddleware(searchForIndexHtml: &lt;span style=&#34;color:#f5a97f&#34;&gt;true&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;static404middleware&#34;&gt;Static404Middleware&lt;/h3&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;Hummingbird&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#eed49f&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;Static404Middleware&lt;/span&gt;&amp;lt;&lt;span style=&#34;color:#eed49f&#34;&gt;Context&lt;/span&gt;: &lt;span style=&#34;color:#eed49f&#34;&gt;RequestContext&lt;/span&gt;&amp;gt;: &lt;span style=&#34;color:#eed49f&#34;&gt;RouterMiddleware&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;handle&lt;/span&gt;(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; request: Request,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        context: Context,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        next: (
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            Request,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            Context
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        ) async &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; -&amp;gt; Response
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    ) async &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; -&amp;gt; Response {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;do&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; await next(request, context)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;catch&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;error&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;as&lt;/span&gt; HTTPError {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; error.status == .notFound {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; Response(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    status: .seeOther,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    headers: [
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                        .location: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;/404.html&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    ]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                )
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;throw&lt;/span&gt; error
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And the static page:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-HTML&#34; data-lang=&#34;HTML&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&amp;lt;!DOCTYPE html&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;html&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;head&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &amp;lt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;title&lt;/span&gt;&amp;gt;Wrong turn.&amp;lt;/&lt;span style=&#34;color:#c6a0f6&#34;&gt;title&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &amp;lt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;meta&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;charset&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;UTF-8&amp;#34;&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;/&lt;span style=&#34;color:#c6a0f6&#34;&gt;head&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;body&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &amp;lt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;H1&lt;/span&gt;&amp;gt;Return to the route.&amp;lt;/&lt;span style=&#34;color:#c6a0f6&#34;&gt;H1&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;/&lt;span style=&#34;color:#c6a0f6&#34;&gt;body&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;/&lt;span style=&#34;color:#c6a0f6&#34;&gt;html&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;If that&amp;rsquo;s too uninformative, don&amp;rsquo;t reach for Javascript&amp;rsquo;s &lt;a href=&#34;https://www.w3.org/TR/DOM-Level-2-HTML/html.html#ID-46183437&#34;&gt;&lt;code&gt;Document.URL&lt;/code&gt;&lt;/a&gt; to pass query args and build a dynamic page that way. Hummingbird&amp;rsquo;s RIGHT HERE to make that dynamic page itself.&lt;/p&gt;
&lt;h2 id=&#34;return-dynamic-page&#34;&gt;Return Dynamic Page&lt;/h2&gt;
&lt;p&gt;This section leans on the &lt;a href=&#34;https://whynotestflight.com/excuses/how-do-i-get-hummingbird-to-serve-html-dynamically/&#34;&gt;previous post on Mustache&lt;/a&gt; and code from the &lt;a href=&#34;https://github.com/hummingbird-project/hummingbird-examples/blob/97a09f0664679f017616a82894848b267c5e7068/todos-auth-fluent/Sources/App/Middleware/ErrorPageMiddleware.swift&#34;&gt;auth-fluent example&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The resulting middleware will serve a 404 without any redirection. If the endpoint won&amp;rsquo;t ever hold valid content that&amp;rsquo;s a great choice. But not just 404&amp;rsquo;s, it will also provide a page for ANY error using an &lt;code&gt;ErrorHTML&lt;/code&gt; builder.&lt;/p&gt;
&lt;h3 id=&#34;errorpagemiddleware&#34;&gt;ErrorPageMiddleware&lt;/h3&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;Hummingbird&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;Mustache&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;/// Generate an HTML page for a thrown error&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;ErrorPageMiddleware&lt;/span&gt;&amp;lt;Context: RequestContext&amp;gt;: RouterMiddleware {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;mustacheLibrary&lt;/span&gt;: MustacheLibrary
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;handle&lt;/span&gt;(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; request: Request,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        context: Context,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        next: (Request, Context) async &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; -&amp;gt; Response
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    ) async &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; -&amp;gt; Response {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;do&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; await next(request, context)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        } &lt;span style=&#34;color:#c6a0f6&#34;&gt;catch&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;error&lt;/span&gt; = error &lt;span style=&#34;color:#c6a0f6&#34;&gt;as&lt;/span&gt;? HTTPError {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; ErrorHTML(status: error.status, message: error.body ?? &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;, library: mustacheLibrary).response(from: request, context: context)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            } &lt;span style=&#34;color:#c6a0f6&#34;&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; ErrorHTML(status: HTTPResponse.Status.internalServerError, message: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;error&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;, library: mustacheLibrary).response(from: request, context: context)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;errorhtml&#34;&gt;ErrorHTML&lt;/h3&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;Hummingbird&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;Mustache&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;ErrorInfo&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;title&lt;/span&gt;: &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;status&lt;/span&gt;: &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;message&lt;/span&gt;: &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;ErrorHTML&lt;/span&gt;:ResponseGenerator  {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;message&lt;/span&gt;: &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;status&lt;/span&gt;: HTTPResponse.Status
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;library&lt;/span&gt;: MustacheLibrary
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;init&lt;/span&gt;(status: HTTPResponse.Status, message: &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;, library:MustacheLibrary) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;.message = message
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;.status = status
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;.library = library
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//should probably check library for the error template. &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;private&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;html&lt;/span&gt;:&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;result&lt;/span&gt; = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt;? render() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; result
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        } &lt;span style=&#34;color:#c6a0f6&#34;&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;??? oops.&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;private&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;render&lt;/span&gt;() &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; -&amp;gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;? {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;pageContent&lt;/span&gt; = ErrorInfo(title: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Error Finding Page&amp;#34;&lt;/span&gt;, status: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;status&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;, message: message)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;rendered&lt;/span&gt; = library.render(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            pageContent,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            withTemplate: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;error&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        )
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; rendered
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;response&lt;/span&gt;(from request: Request, context: some RequestContext) &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; -&amp;gt; Response {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;buffer&lt;/span&gt; = ByteBuffer(string: &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;.html)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; .&lt;span style=&#34;color:#ed8796&#34;&gt;init&lt;/span&gt;(status: status, headers: [.contentType: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;text/html&amp;#34;&lt;/span&gt;], body: .&lt;span style=&#34;color:#ed8796&#34;&gt;init&lt;/span&gt;(byteBuffer: buffer))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;img src=&#34;static_error.png&#34; alt=&#34;screen shot of browser window that says &amp;ldquo;Return to the Route&amp;rdquo; in the default font as an H1 title and nothing after it visible.&#34;&gt;&lt;/p&gt;
&lt;h3 id=&#34;the-mustache-templates&#34;&gt;The Mustache Templates&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;error.mustache&lt;/code&gt; calls &lt;code&gt;head.mustache&lt;/code&gt; and &lt;code&gt;foot.mustache&lt;/code&gt;, all in the &lt;a href=&#34;https://github.com/carlynorama/HummingbirdExamples/tree/main/07_middleware/inthemiddle/Sources/inthemiddle/Templates&#34;&gt;Templates folder&lt;/a&gt; included in &lt;a href=&#34;https://github.com/carlynorama/HummingbirdExamples/blob/main/07_middleware/inthemiddle/Package.swift&#34;&gt;Package.swift&lt;/a&gt;.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-html&#34; data-lang=&#34;html&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{{&amp;gt;head}}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;body&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &amp;lt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;h1&lt;/span&gt;&amp;gt;Error&amp;lt;/&lt;span style=&#34;color:#c6a0f6&#34;&gt;h1&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &amp;lt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;h2&lt;/span&gt;&amp;gt;{{  status  }}&amp;lt;/&lt;span style=&#34;color:#c6a0f6&#34;&gt;h2&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &amp;lt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;p&lt;/span&gt;&amp;gt;{{  message  }}&amp;lt;/&lt;span style=&#34;color:#c6a0f6&#34;&gt;p&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;/&lt;span style=&#34;color:#c6a0f6&#34;&gt;body&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{{&amp;gt;foot}}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-html&#34; data-lang=&#34;html&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&amp;lt;!DOCTYPE html&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;html&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;head&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &amp;lt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;title&lt;/span&gt;&amp;gt;{{  title  }}&amp;lt;/&lt;span style=&#34;color:#c6a0f6&#34;&gt;title&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &amp;lt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;meta&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;charset&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;UTF-8&amp;#34;&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;/&lt;span style=&#34;color:#c6a0f6&#34;&gt;head&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-html&#34; data-lang=&#34;html&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;/&lt;span style=&#34;color:#c6a0f6&#34;&gt;html&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;adding-the-middleware-and-templates&#34;&gt;Adding the Middleware and Templates&lt;/h3&gt;
&lt;p&gt;in the &lt;code&gt;buildRouter&lt;/code&gt; function&amp;hellip;&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;mustacheLibrary&lt;/span&gt; = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; await MustacheLibrary(directory: Bundle.module.resourcePath!)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  router.addMiddleware {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//Mustache based error page.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    ErrorPageMiddleware(mustacheLibrary: mustacheLibrary)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;img src=&#34;dynamic_error.png&#34; alt=&#34;screen shot of browser window that says &amp;ldquo;Error&amp;rdquo; as an H1 title and &amp;ldquo;Not Found 404&amp;rdquo; as H2 with nothing after it visible. This is all in the in the default font. No styling added.&#34;&gt;&lt;/p&gt;
&lt;h2 id=&#34;return-json&#34;&gt;Return JSON&lt;/h2&gt;
&lt;p&gt;But what if the app serves a JSON API and serving HTML doesn&amp;rsquo;t make sense?&lt;/p&gt;
&lt;p&gt;While an empty body can absolutely be a valid choice, this example takes an initial crack at returning a &lt;a href=&#34;https://www.rfc-editor.org/rfc/rfc7807&#34;&gt;Problem Details&lt;/a&gt; &lt;a href=&#34;https://swagger.io/blog/problem-details-rfc9457-api-error-handling/&#34;&gt;JSON&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;If the client doesn&amp;rsquo;t specify that &amp;ldquo;text/html&amp;rdquo; is an accepted format, it will return JSON. That means clients that accept &amp;ldquo;&lt;em&gt;/&lt;/em&gt;&amp;rdquo; but don&amp;rsquo;t call out &amp;ldquo;text/html&amp;rdquo; specifically will get the JSON. The &lt;a href=&#34;https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Accept&#34;&gt;accepts list&lt;/a&gt; uses specificity and a &lt;a href=&#34;https://developer.mozilla.org/en-US/docs/Glossary/Quality_values&#34;&gt;quality factor&lt;/a&gt; to rank types accepted. This middleware doesn&amp;rsquo;t care, but a future version probably should.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;Hummingbird&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;Logging&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;ProblemDetail&lt;/span&gt;: Decodable, ResponseEncodable {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;status&lt;/span&gt;: &lt;span style=&#34;color:#91d7e3&#34;&gt;Int&lt;/span&gt;?
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;title&lt;/span&gt;: &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;detail&lt;/span&gt;: &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;?
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#ed8796&#34;&gt;init&lt;/span&gt;(withStatus: HTTPResponse.Status, details: &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;.status = withStatus.code
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;.title = &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;withStatus.code&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;: &lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;withStatus.reasonPhrase&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;.detail = details
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;JSONErrorMiddleware&lt;/span&gt;&amp;lt;Context: RequestContext&amp;gt;: RouterMiddleware {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#ed8796&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;handle&lt;/span&gt;(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; request: Request, context: Context, next: (Request, Context) async &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; -&amp;gt; Response
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  ) async &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; -&amp;gt; Response {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;do&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; await next(request, context)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    } &lt;span style=&#34;color:#c6a0f6&#34;&gt;catch&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;error&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;as&lt;/span&gt; HTTPError {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;accepts&lt;/span&gt; = request.headers[.accept] {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;!&lt;/span&gt;accepts.&lt;span style=&#34;color:#91d7e3&#34;&gt;contains&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;text/html&amp;#34;&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;problem&lt;/span&gt; = ProblemDetail(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            withStatus: error.status, 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            details: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;error&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt; from request to &lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;request.uri&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;response&lt;/span&gt; = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; problem.response(from: request, context: context)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          response.status = error.status
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          response.headers[.contentType] = &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;application/problem+json&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; response
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#c6a0f6&#34;&gt;throw&lt;/span&gt; error
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;img src=&#34;json_error.png&#34; alt=&#34;screen shot of a terminal window that has the curl call and the problem detail json response showing.&#34;&gt;&lt;/p&gt;
&lt;h2 id=&#34;middleware-for-a-whole-route-block&#34;&gt;Middleware for a whole Route Block&lt;/h2&gt;
&lt;p&gt;I know I will want to apply Middleware to a whole block of routes. That can be done with the trie router, but only for the happy paths. So, for example if you want to use an authentication middleware for anything filed under &lt;code&gt;/private/&lt;/code&gt; all the routes under &lt;code&gt;/private/&lt;/code&gt; that have a description will call that middleware no problem.&lt;/p&gt;
&lt;p&gt;I saw a handful of different ways in the examples, but an &lt;a href=&#34;https://github.com/search?q=repo%3Ahummingbird-project%2Fhummingbird-examples%20addRoutes&amp;amp;type=code&#34;&gt;addRoutes function&lt;/a&gt; seems to work the most reliably (e.g.):&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;addRoutes&lt;/span&gt;(to router: Router&amp;lt;AppRequestContext&amp;gt;, atPath:RouterPath) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    router.group(atPath)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        .add(middleware: AlmostEmptyMiddleware&amp;lt;AppRequestContext&amp;gt;(message: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;controller method&amp;#34;&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        .&lt;span style=&#34;color:#c6a0f6&#34;&gt;get&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;tryme&amp;#34;&lt;/span&gt;) { &lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt;, &lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            ExampleCodable(name: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Diane&amp;#34;&lt;/span&gt;, number: &lt;span style=&#34;color:#f5a97f&#34;&gt;3&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;That middleware will only fire for the route &lt;code&gt;&amp;quot;\(atPath)/tryme&amp;quot;&lt;/code&gt;, not &lt;code&gt;&amp;quot;\(atPath)/nothinghere&amp;quot;&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;If I wanted something to fire for all of &lt;code&gt;&amp;quot;\(atPath)/&amp;quot;&lt;/code&gt; I would have to use the &lt;a href=&#34;https://docs.hummingbird.codes/2.0/documentation/hummingbird/routerbuilderguide#Differences-from-trie-router&#34;&gt;ResultBuilderRouter&lt;/a&gt; instead of the trie and I haven&amp;rsquo;t touched that much yet at all.&lt;/p&gt;
&lt;p&gt;Another option would be lots of little apps glued together by a &lt;a href=&#34;https://en.wikipedia.org/wiki/Proxy_server&#34;&gt;Proxy server&lt;/a&gt;. Perhaps tricky to set up, but possibly easier to maintain in the long run since an error in the JSON api wouldn&amp;rsquo;t bring down the web server, etc. Use a data backend like postgres that can manage multiple client interactions well if that&amp;rsquo;s needed.&lt;/p&gt;
&lt;h2 id=&#34;summary&#34;&gt;Summary&lt;/h2&gt;
&lt;p&gt;Middleware is the perfect place to catch and filter errors, but the information gleaned by a Middleware can only be kept around in &lt;em&gt;that&lt;/em&gt; Middleware. Unless it gets added to a &lt;a href=&#34;https://docs.hummingbird.codes/2.0/documentation/hummingbird/requestcontexts/&#34;&gt;RequestContext&lt;/a&gt;, which will be the next Hummingbird example.&lt;/p&gt;
</description>
    </item>
    
    
    
    <item>
      <title>So how exactly does Middleware come into Hummingbird?</title>
      <link>https://whynotestflight.com/excuses/so-how-exactly-does-middleware-come-into-hummingbird/</link>
      <pubDate>Fri, 26 Sep 2025 00:00:00 +0000</pubDate>
      
      <guid>https://whynotestflight.com/excuses/so-how-exactly-does-middleware-come-into-hummingbird/</guid>
      <description>&lt;p&gt;So &lt;a href=&#34;https://github.com/carlynorama/HummingbirdExamples/&#34;&gt;previous examples&lt;/a&gt; are already using Hummingbird provided &lt;a href=&#34;https://docs.hummingbird.codes/2.0/documentation/hummingbird/middlewareguide&#34;&gt;Middleware&lt;/a&gt;.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://docs.hummingbird.codes/2.0/documentation/hummingbird/loggingmetricsandtracing&#34;&gt;Logging Middleware&lt;/a&gt; which determines what gets logged out to the terminal while running, a skin around &lt;a href=&#34;https://github.com/apple/swift-log&#34;&gt;swift-log&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://docs.hummingbird.codes/2.0/documentation/hummingbird/filemiddleware&#34;&gt;File Middleware&lt;/a&gt; which serves up static pages when there&amp;rsquo;s no route for the same path defined in the Router&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Other &lt;a href=&#34;https://github.com/hummingbird-project/hummingbird/tree/main/Sources/Hummingbird/Middleware&#34;&gt;Middlewares provided&lt;/a&gt; include:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://docs.hummingbird.codes/2.0/documentation/hummingbird/corsmiddleware&#34;&gt;CORS Middleware&lt;/a&gt; for managing &lt;a href=&#34;https://en.wikipedia.org/wiki/Cross-origin_resource_sharing&#34;&gt;Cross-origin resource sharing&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://docs.hummingbird.codes/2.0/documentation/hummingbird/metricsmiddleware&#34;&gt;Metrics Middleware&lt;/a&gt; The same way the logging middleware wraps swift-log this wraps &lt;a href=&#34;https://github.com/apple/swift-metrics&#34;&gt;swift-metrics&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://docs.hummingbird.codes/2.0/documentation/hummingbird/tracingmiddleware&#34;&gt;Tracing&lt;/a&gt; Provides a &lt;a href=&#34;https://en.wikipedia.org/wiki/Tracing_(software)&#34;&gt;tracing&lt;/a&gt; interface &lt;a href=&#34;https://github.com/apple/swift-distributed-tracing&#34;&gt;distributed tracing&lt;/a&gt; (&lt;a href=&#34;https://www.w3.org/groups/wg/distributed-tracing/&#34;&gt;W3 working group&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Hummingbird also provides some Middleware protocols to help get common tasks started:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://docs.hummingbird.codes/2.0/documentation/hummingbirdauth/authenticatormiddleware&#34;&gt;AuthenticatorMiddleware&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;A whole &lt;a href=&#34;https://github.com/hummingbird-project/hummingbird-auth&#34;&gt;Authentication framework&lt;/a&gt; provided as a library as well.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://docs.hummingbird.codes/2.0/documentation/hummingbirdauth/sessionmiddleware&#34;&gt;SessionMiddleware&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://docs.hummingbird.codes/2.0/documentation/hummingbirdcompression/requestdecompressionmiddleware/&#34;&gt;RequestDecompression&lt;/a&gt; and &lt;a href=&#34;https://docs.hummingbird.codes/2.0/documentation/hummingbirdcompression/responsecompressionmiddleware/&#34;&gt;ResponseCompression&lt;/a&gt; Middlewares&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Not to mention the many &lt;a href=&#34;https://github.com/search?q=org%3Ahummingbird-project%20Middleware&amp;amp;type=code&#34;&gt;examples in the various repos&lt;/a&gt; of the Hummingbird Project itself.&lt;/p&gt;
&lt;p&gt;But what if you want to write your own?&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;m going to show 3 over the next 3 posts:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;a middleware that will log out header information&lt;/li&gt;
&lt;li&gt;one that falls back to an error page&lt;/li&gt;
&lt;li&gt;one that saves information in the context for later use&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;middleware&#34;&gt;Middleware&lt;/h2&gt;
&lt;p&gt;This middleware isn&amp;rsquo;t strictly needed for logging request header information because the &lt;a href=&#34;https://github.com/hummingbird-project/hummingbird/blob/9f422e0f79dbcc8613c891148076664f264a2625/Sources/Hummingbird/Middleware/LogRequestMiddleware.swift&#34;&gt;Logging middleware&lt;/a&gt; already handles it in a far more robust and ergonomic way.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        LogRequestsMiddleware(.info, includeHeaders: .some([.contentType]))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        LogRequestsMiddleware(.info, includeHeaders: .all())
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        LogRequestsMiddleware(.info, includeHeaders: .all(except: [.cookie]))
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;What this middleware will show is &lt;em&gt;also&lt;/em&gt; logging the response headers, albeit in a much more rudimentary way.&lt;/p&gt;
&lt;p&gt;Middleware requires a handler that calls the next middleware on the stack, but since that call happens inside the handler, that method can also operate on the &lt;code&gt;Response&lt;/code&gt; bubbling up as well.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;EmptyMiddleware&lt;/span&gt;&amp;lt;Context: RequestContext&amp;gt;: RouterMiddleware {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;handle&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; request: Request, context: Context, next: (Request, Context) async &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; -&amp;gt; Response) async &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; -&amp;gt; Response {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; await next(request, context)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;So if I wanted to write a middleware that would show the headers for BOTH the request and the response it might look something like:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;Hummingbird&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;Logging&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;LogHeadersMiddleware&lt;/span&gt;&amp;lt;Context: RequestContext&amp;gt;: RouterMiddleware {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;level&lt;/span&gt;:Logger.Level
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;formatHeaderForLog&lt;/span&gt;(headers: HTTPFields) -&amp;gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;forLog&lt;/span&gt; = &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;for&lt;/span&gt; header &lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt; headers {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            forLog.append(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\t&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;header.name&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;header.value&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\n&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        forLog.append(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;------&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; forLog
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;handle&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; request: Request, context: Context, next: (Request, Context) async &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; -&amp;gt; Response) async &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; -&amp;gt; Response {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;requestHeaders&lt;/span&gt; = formatHeaderForLog(headers: request.headers)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        context.logger.log(level: level, Logger.Message(stringLiteral: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\n&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;Headers for &lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;request.uri.path&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt; request:&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\n&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;requestHeaders&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//return Response&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;response&lt;/span&gt; = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; await next(request, context)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;responseHeaders&lt;/span&gt; = formatHeaderForLog(headers: response.headers)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        context.logger.log(level: level, Logger.Message(stringLiteral: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\n&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;Responding with:&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\n&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;responseHeaders&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; response
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The output for a curl request to the &lt;a href=&#34;https://github.com/carlynorama/HummingbirdExamples/blob/30f76b6a7b098ba58ee71c69209e498ed3f63309/07_middleware/inthemiddle/Sources/inthemiddle/Application%2Bbuild.swift#L62&#34;&gt;/hello route in the demo&lt;/a&gt; (&lt;code&gt;curl &amp;quot;http://localhost:8080/hello&amp;quot;&lt;/code&gt;) looks like:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;2025-09-26T06:20:35-0700 info inthemiddle: hb.request.id&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt;2f72a050b4afa3a2698b886b64654226 &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;[&lt;/span&gt;inthemiddle&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;]&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Headers &lt;span style=&#34;color:#c6a0f6&#34;&gt;for&lt;/span&gt; /hello request:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        User-Agent:curl/8.7.1
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        Accept:*/*
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;------
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;2025-09-26T06:20:35-0700 info inthemiddle: hb.request.id&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt;2f72a050b4afa3a2698b886b64654226 &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;[&lt;/span&gt;inthemiddle&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;]&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Responding with:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        Content-Type:text/plain; &lt;span style=&#34;color:#f4dbd6&#34;&gt;charset&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt;utf-8
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        Content-Length:5
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;------
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;order-matters&#34;&gt;Order Matters&lt;/h3&gt;
&lt;p&gt;Let&amp;rsquo;s see what happens with the middleware called from two different places: right after the normal logger and at the end.&lt;/p&gt;
&lt;p&gt;First right after the usual logger.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    router.addMiddleware {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// logging middleware&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        LogRequestsMiddleware(.info)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//logs the headers of the request and the responses&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        LogHeadersMiddleware(level: .info)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//serves the static files in public folder by default.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        FileMiddleware(searchForIndexHtml: &lt;span style=&#34;color:#f5a97f&#34;&gt;true&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Calling the home page which has a static HTML page available (&lt;code&gt;curl &amp;quot;http://localhost:8080/&amp;quot;&lt;/code&gt;) the built in Logger prints out first and the custom logger prints out everything second. If the FileMiddleware logged anything, it would have shown up where noted in the added comment.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;2025-09-26T06:31:44-0700 info inthemiddle: hb.request.id&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt;94e54b3188d6f6c807d5eed484bca2cb hb.request.method&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt;GET hb.request.path&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt;/ &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;[&lt;/span&gt;Hummingbird&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;]&lt;/span&gt; Request
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;2025-09-26T06:31:44-0700 info inthemiddle: hb.request.id&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt;94e54b3188d6f6c807d5eed484bca2cb &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;[&lt;/span&gt;inthemiddle&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;]&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Headers &lt;span style=&#34;color:#c6a0f6&#34;&gt;for&lt;/span&gt; / request:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        User-Agent:curl/8.7.1
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        Accept:*/*
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;------
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# FileMiddleware logging would have happened here! &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;2025-09-26T06:31:44-0700 info inthemiddle: hb.request.id&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt;94e54b3188d6f6c807d5eed484bca2cb &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;[&lt;/span&gt;inthemiddle&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;]&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Responding with:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        Content-Length:364
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        Last-Modified:Tue, &lt;span style=&#34;color:#f5a97f&#34;&gt;16&lt;/span&gt; Sep &lt;span style=&#34;color:#f5a97f&#34;&gt;2025&lt;/span&gt; 16:40:02 GMT
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        ETag:W/&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;0900180b0600303830322e3932373739&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        Content-Type:text/html
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        Accept-Ranges:bytes
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;------
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now move &lt;code&gt;LogHeadersMiddleware&lt;/code&gt; AFTER the file middleware.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    router.addMiddleware {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// logging middleware&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        LogRequestsMiddleware(.info)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//serves the static files in public folder by default.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        FileMiddleware(searchForIndexHtml: &lt;span style=&#34;color:#f5a97f&#34;&gt;true&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//logs the headers of the request and the responses&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        LogHeadersMiddleware(level: .info)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;There&amp;rsquo;s NOTHING for the response because there isn&amp;rsquo;t one yet. Nothing in the Hummingbird stack has prepped one because there isn&amp;rsquo;t a route for &amp;ldquo;/&amp;rdquo; in the router at all. Not until it goes back up through the FileMiddleware will it have the index page Response in hand.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;2025-09-26T06:36:24-0700 info inthemiddle: hb.request.id&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt;eb458259999c78dc5069ba5bc9205f41 &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;[&lt;/span&gt;inthemiddle&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;]&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Headers &lt;span style=&#34;color:#c6a0f6&#34;&gt;for&lt;/span&gt; / request:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        User-Agent:curl/8.7.1
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        Accept:*/*
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;------
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The next test is to move the middleware to the top and call a known undefined path (no route, no static page.) (&lt;code&gt;curl &amp;quot;http://localhost:8080/knownempty&amp;quot;&lt;/code&gt;)&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    router.addMiddleware {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//logs the headers of the request and the responses&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        LogHeadersMiddleware(level: .info)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// logging middleware&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        LogRequestsMiddleware(.info)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//serves the static files in public folder by default.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        FileMiddleware(searchForIndexHtml: &lt;span style=&#34;color:#f5a97f&#34;&gt;true&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;It&amp;rsquo;s exactly the same, request headers print and nothing for response headers.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;2025-09-26T06:42:48-0700 info inthemiddle: hb.request.id&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt;eb458259999c78dc5069ba5bc9205f43 &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;[&lt;/span&gt;inthemiddle&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;]&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Headers &lt;span style=&#34;color:#c6a0f6&#34;&gt;for&lt;/span&gt; /knownempty request:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        User-Agent:curl/8.7.1
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        Accept:*/*
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;------
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The curl call printed out nothing as well. That will change if change the curl call to (&lt;code&gt;curl -i &amp;quot;http://localhost:8080/knownempty&amp;quot;&lt;/code&gt;), in which case the logs will not print out a response, but the curl will be:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;HTTP/1.1 404 Not Found
Content-Length: 0
Date: Fri, 26 Sep 2025 15:49:48 GMT
Server: inthemiddle
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;So when does Hummingbird formulate that Response? There is an &lt;a href=&#34;https://github.com/hummingbird-project/hummingbird/blob/main/Sources/Hummingbird/Error/HTTPError.swift&#34;&gt;HTTPError&lt;/a&gt; (&lt;a href=&#34;https://docs.hummingbird.codes/2.0/documentation/hummingbird/errorhandling&#34;&gt;docs&lt;/a&gt;) type that gets propagated up instead of a &lt;code&gt;Response&lt;/code&gt; as part of the &lt;code&gt;try&lt;/code&gt; in the &lt;code&gt;try await next(request, context)&lt;/code&gt; call. The not found error gets thrown in the &lt;a href=&#34;https://github.com/hummingbird-project/hummingbird/blob/9f422e0f79dbcc8613c891148076664f264a2625/Sources/Hummingbird/Router/RouterResponder.swift#L44&#34;&gt;&lt;code&gt;respond&lt;/code&gt; method&lt;/a&gt; by the &lt;a href=&#34;https://github.com/hummingbird-project/hummingbird/blob/9f422e0f79dbcc8613c891148076664f264a2625/Sources/Hummingbird/Router/RouterResponder.swift#L56&#34;&gt;notFoundResponder&lt;/a&gt; of the &lt;a href=&#34;https://github.com/hummingbird-project/hummingbird/blob/main/Sources/Hummingbird/Router/RouterResponder.swift&#34;&gt;&lt;code&gt;RouterResponder&lt;/code&gt;&lt;/a&gt;&amp;rsquo;s that the application builds from the &lt;code&gt;Router&lt;/code&gt; passed to it at startup.&lt;/p&gt;
&lt;p&gt;So how to catch it and swap in something else? More middleware!&lt;/p&gt;
&lt;h2 id=&#34;summary&#34;&gt;Summary&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;LogHeadersMiddleware&lt;/code&gt; demonstrates interceding on a path to punt out headers to the logging system. The next demo will show how to catch undefined routes to return appropriate 404 responses.&lt;/p&gt;
</description>
    </item>
    
    
    
    <item>
      <title>Can I make the button more pressable?</title>
      <link>https://whynotestflight.com/excuses/can-i-make-the-button-more-pressable/</link>
      <pubDate>Thu, 25 Sep 2025 00:00:00 +0000</pubDate>
      
      <guid>https://whynotestflight.com/excuses/can-i-make-the-button-more-pressable/</guid>
      <description>&lt;p&gt;So this project needs it&amp;rsquo;s button situation improved. The little boot button that I&amp;rsquo;m pressing with a bamboo skewer isn&amp;rsquo;t going to cut it.&lt;/p&gt;
&lt;p&gt;Also I want to make the HTTP call &amp;ldquo;onPress&amp;rdquo;, not a repeat timer nor &amp;ldquo;while pressed&amp;rdquo;. I need to add that feature to &lt;code&gt;MomentaryInput&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;For state of the code at the end of these notes see:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/carlynorama/swift_esp32c6_hello/tree/f_inputBehaviors&#34;&gt;https://github.com/carlynorama/swift_esp32c6_hello/tree/f_inputBehaviors&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;new-parts&#34;&gt;New Parts&lt;/h2&gt;
&lt;p&gt;So I bought some parts from Adafruit. I generally buy 2 of each thing because accidents happen.&lt;/p&gt;
&lt;p&gt;Desired Button:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;http://www.adafruit.com/product/5123#tutorials&#34;&gt;Kailh Mechanical Key Switch - Clicky Blue&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;http://www.adafruit.com/product/5695#tutorials&#34;&gt;Adafruit NeoKey BFF for Mechanical Key Add-On for QT Py and Xiao&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Fallback Button (only 1x because its a fall back anyway):&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;http://www.adafruit.com/product/5666#tutorials&#34;&gt;Adafruit IoT Button with NeoPixel BFF Add-On for QT Py and Xiao&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If decide to take on battery power:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;http://www.adafruit.com/product/5397#tutorials&#34;&gt;Adafruit LiIon or LiPoly Charger BFF Add-On for QT Py&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;http://www.adafruit.com/product/4236#tutorials&#34;&gt;Lithium Ion Polymer Battery with Short Cable - 3.7V 420mAh&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Short USB C cable:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;http://www.adafruit.com/product/4198#tutorials&#34;&gt;USB C to USB C Cable - USB 3.1 Gen 4 with E-Mark&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;3 sets of headers went in to assembling the prototype, each a different type.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;the low profile pin headers that &lt;a href=&#34;https://www.adafruit.com/product/3009&#34;&gt;came with the button BFF&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://www.adafruit.com/product/3366&#34;&gt;deep socket headers&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://www.adafruit.com/product/3008&#34;&gt;lower profile socket headers&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;These all need to be cut down to a length of 7, so if bulk sourcing getting them &lt;a href=&#34;https://www.digikey.com/en/products/filter/rectangular-connectors/headers-receptacles-female-sockets/315?s=N4IgjCBcoBw1oDGUBmBDANgZwKYBoQB7KAbRACYA2AdhnIFYQBdAgBwBcoQBldgJwCWAOwDmIAL6SgA&#34;&gt;precut&lt;/a&gt; is easier.&lt;/p&gt;
&lt;p&gt;Not gonna lie, my husband &lt;a href=&#34;https://mastodon.social/@todbot&#34;&gt;todbot&lt;/a&gt; zipped these on for me since he&amp;rsquo;s in the middle of a soldering palooza. (Adafruit tutorial on &lt;a href=&#34;https://www.youtube.com/watch?v=Z0joOKaQ43A&#34;&gt;soldering headers&lt;/a&gt; and &lt;a href=&#34;https://www.youtube.com/playlist?list=PLfbQcOtLPyIHoDDBP5d-OuTpQmCyjCMJb&#34;&gt;my old play list&lt;/a&gt; on soldering in general) I traded firmware-loading duties later in the week.  Hero shot for my hero!&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;hero_button.jpg&#34; alt=&#34;A small tower of three stories. The bottom level being the Xiao, which one can tell from the USB-C port, the middle one the battery BFF, and the top of the spire is a white key cap.&#34;&gt;&lt;/p&gt;
&lt;p&gt;To test the new hardware, move the button pin:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//new button on pin 2 instead of on the boot pin (9)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#c6a0f6&#34;&gt;guard&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;button&lt;/span&gt; = MomentaryInput(&lt;span style=&#34;color:#f5a97f&#34;&gt;2&lt;/span&gt;) &lt;span style=&#34;color:#c6a0f6&#34;&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#91d7e3&#34;&gt;fatalError&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Difficulty setting up button.&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;return it to a simple switch&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; button.isActive {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  led.turnOn()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;} &lt;span style=&#34;color:#c6a0f6&#34;&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  led.turnOff()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;delay(&lt;span style=&#34;color:#f5a97f&#34;&gt;50&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Why the delay? because without it the esp-if monitor gets a little overwhelmed.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Please &lt;span style=&#34;color:#91d7e3&#34;&gt;enable&lt;/span&gt; CONFIG_ESP_SYSTEM_USE_FRAME_POINTER option to have a full backtrace.
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;E &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;(&lt;/span&gt;24238&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;)&lt;/span&gt; task_wdt: Task watchdog got triggered. The following tasks/users did not reset the watchdog in time:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;E &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;(&lt;/span&gt;24238&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;)&lt;/span&gt; task_wdt:  - IDLE &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;(&lt;/span&gt;CPU 0&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;E &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;(&lt;/span&gt;24238&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;)&lt;/span&gt; task_wdt: Tasks currently running:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;E &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;(&lt;/span&gt;24238&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;)&lt;/span&gt; task_wdt: CPU 0: main
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;E &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;(&lt;/span&gt;24238&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;)&lt;/span&gt; task_wdt: Print CPU &lt;span style=&#34;color:#f5a97f&#34;&gt;0&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;(&lt;/span&gt;current core&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;)&lt;/span&gt; registers
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Core  &lt;span style=&#34;color:#f5a97f&#34;&gt;0&lt;/span&gt; register dump:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;MEPC    : 0x4200b03a  RA      : 0x4200b03a  SP      : 0x40811000  GP      : 0x4080bfa4  
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;--- 0x4200b03a: &lt;span style=&#34;color:#f4dbd6&#34;&gt;$e10__idf_main0B0yyF&lt;/span&gt; at ??:?
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;--- 0x4200b03a: &lt;span style=&#34;color:#f4dbd6&#34;&gt;$e10__idf_main0B0yyF&lt;/span&gt; at ??:?
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;TP      : 0x40811060  T0      : 0x4200b088  T1      : 0x20000000  T2      : 0xffffffff  
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;--- 0x4200b088: &lt;span style=&#34;color:#f4dbd6&#34;&gt;$es5print_10terminatorys12StaticStringV_ADtF&lt;/span&gt; at ??:?
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;S0/FP   : 0x0000000f  S1      : 0x00000001  A0      : 0x00000000  A1      : 0x00000001  
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;A2      : 0x00000000  A3      : 0x00000004  A4      : 0x00008000  A5      : 0x60091000  
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;A6      : 0x00000001  A7      : 0x0000000a  S2      : 0x42020550  S3      : 0x00000000  
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;S4      : 0x00000000  S5      : 0x00000000  S6      : 0x00000000  S7      : 0x00000000  
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;S8      : 0x00000000  S9      : 0x00000000  S10     : 0x00000000  S11     : 0x00000000  
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;T3      : 0x00000000  T4      : 0x00000000  T5      : 0x00000000  T6      : 0x00000000  
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;MSTATUS : 0x00001889  MTVEC   : 0x40800001  MCAUSE  : 0xdeadc0de  MTVAL   : 0xdeadc0de  
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;--- 0x40800001: _vector_table at /Users/&lt;span style=&#34;color:#f4dbd6&#34;&gt;$USER&lt;/span&gt;/esp/esp-idf/components/riscv/vectors_intc.S:54
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;MHARTID : 0x00000000  
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;the-new-code&#34;&gt;The New Code&lt;/h2&gt;
&lt;p&gt;Because modern buttons are so great, and because I&amp;rsquo;ve picked one with a real CLICK to it I am not going to worry about a &lt;a href=&#34;https://www.digikey.com/en/maker/tutorials/2024/how-to-implement-a-software-based-debounce-algorithm-for-button-inputs-on-a-microcontroller&#34;&gt;software debounce&lt;/a&gt; yet. On this chip I could activate the Espressif provided &lt;a href=&#34;https://docs.espressif.com/projects/esp-idf/en/latest/esp32c6/api-reference/peripherals/gpio.html#gpio-glitch-filter&#34;&gt;glitch filter&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&#34;added-inverse-to-gpiolevel&#34;&gt;Added Inverse to GPIOLevel&lt;/h3&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;extension&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;GPIOLevel&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;inverse&lt;/span&gt;:GPIOLevel {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        (&lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt; == .high) ? .high : .low
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;updates-to-momentaryinput&#34;&gt;Updates to MomentaryInput&lt;/h3&gt;
&lt;p&gt;Added a variable to the struct to store the last state, which will need to be initialized using that inverse value just created.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;extension&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;MomentaryInput&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;init&lt;/span&gt;?(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; pinNum: &lt;span style=&#34;color:#91d7e3&#34;&gt;UInt32&lt;/span&gt;, activeLow:&lt;span style=&#34;color:#91d7e3&#34;&gt;Bool&lt;/span&gt; = &lt;span style=&#34;color:#f5a97f&#34;&gt;true&lt;/span&gt;, useInternalHardware:&lt;span style=&#34;color:#91d7e3&#34;&gt;Bool&lt;/span&gt; = &lt;span style=&#34;color:#f5a97f&#34;&gt;true&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;.pin = InputPin(pinNumber: pinNum, activeLow:activeLow, useInternalHardware: useInternalHardware)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;.activeLevel = GPIOLevel(&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;!&lt;/span&gt;activeLow)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;.lastState = &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;.activeLevel.inverse
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;lastState&lt;/span&gt;:GPIOLevel
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;typealias&lt;/span&gt; OnActiveBehavior = () -&amp;gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;Void&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;mutating&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;onActivate&lt;/span&gt;(&lt;span style=&#34;color:#c6a0f6&#34;&gt;do&lt;/span&gt; behavior:OnActiveBehavior) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;currentLevel&lt;/span&gt; = pin.readLevel()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; currentLevel &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;!=&lt;/span&gt; lastState &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;amp;&amp;amp;&lt;/span&gt; currentLevel == activeLevel {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            behavior()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        lastState = currentLevel
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Since my code will just be using the button for this one behavior it&amp;rsquo;s fine to do the pin read in the call. If I had a lot of behaviors on different button states I&amp;rsquo;d have to be careful not to do a new read for every method, but only once per while loop. Future versions of the code will have to decide if the setup will register listeners, if listeners get called explicitly in the loop, if the button itself will register behaviors to do after the poll&amp;hellip; TBD.&lt;/p&gt;
&lt;p&gt;On a chip like the ESP23C6, it would be even better to hook into their existing &lt;a href=&#34;https://docs.espressif.com/projects/esp-idf/en/latest/esp32c6/api-reference/peripherals/gpio.html#gpio-glitch-filter&#34;&gt;button interrupt types&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;All of that is research for another day. Today is for the easy win.&lt;/p&gt;
&lt;h3 id=&#34;back-on-mainswift&#34;&gt;back on Main.swift&lt;/h3&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#c6a0f6&#34;&gt;while&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;true&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    button.onActivate { &lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;hello&amp;#34;&lt;/span&gt;) }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    delay(&lt;span style=&#34;color:#f5a97f&#34;&gt;50&lt;/span&gt;); 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;TADA! Thats it.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;hello_button.png&#34; alt=&#34;screen shot of a terminal window with the word hello printed repeatedly below green setup text from the esp-idf&#34;&gt;&lt;/p&gt;
&lt;h2 id=&#34;add-the-http-call-back-in&#34;&gt;Add the HTTP call back in&amp;hellip;&lt;/h2&gt;
&lt;p&gt;Where I&amp;rsquo;ve left the &lt;a href=&#34;https://github.com/carlynorama/swift_esp32c6_hello/tree/f_inputBehaviors&#34;&gt;code in the branch&lt;/a&gt; is with the Wifi and HTTP stuff all un commented again and the new while loop looks like:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#c6a0f6&#34;&gt;while&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;true&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    button.onActivate { 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;_&lt;/span&gt; = exampleClient.fetch(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;/&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    delay(&lt;span style=&#34;color:#f5a97f&#34;&gt;50&lt;/span&gt;); &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//to help out the monitor&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Works a treat.&lt;/p&gt;
&lt;h2 id=&#34;summary&#34;&gt;Summary&lt;/h2&gt;
&lt;p&gt;This was a fairly easy task to knock off the list. Especially with a soldering assist.&lt;/p&gt;
&lt;p&gt;More things to do would be to bring the neo-pixel that came on the key cap BFF into the mix to signal different states of the send.&lt;/p&gt;
&lt;p&gt;Theres a bit more &lt;a href=&#34;https://whynotestflight.com/tags/hummingbird/&#34;&gt;server work&lt;/a&gt; to do, too.&lt;/p&gt;
&lt;p&gt;And then both the button and the server have to decide what the secret handshake is going the be for this demo.&lt;/p&gt;
&lt;p&gt;I guess this mean what the next post will be is a bit of a surprise&amp;hellip; even to me!&lt;/p&gt;
</description>
    </item>
    
    
    
    <item>
      <title>Can I Swiftify that ESP32C6 HTTPClient more?</title>
      <link>https://whynotestflight.com/excuses/can-i-swiftify-that-esp32c6-httpclient-more/</link>
      <pubDate>Wed, 24 Sep 2025 00:00:00 +0000</pubDate>
      
      <guid>https://whynotestflight.com/excuses/can-i-swiftify-that-esp32c6-httpclient-more/</guid>
      <description>&lt;p&gt;I&amp;rsquo;m going to straight up lead with my future TODO list, because I&amp;rsquo;m not satisfied with where the code gets left off.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;[] try on MacOS 26 using inline array and span&lt;/li&gt;
&lt;li&gt;[] try on MacOS 26 using new C safety features&lt;/li&gt;
&lt;li&gt;[] Could &lt;code&gt;UnsafeMutablePointer&amp;lt;addrinfo&amp;gt;?&lt;/code&gt; even be a function param? As an inout? Can optionals be inouts?&lt;/li&gt;
&lt;li&gt;[] want a concrete HTTPClient type that links to a HTTPClientService protocol instead of a HTTPClient protocol.&lt;/li&gt;
&lt;li&gt;[] take a whack at serializing the HTTPRequest type w/o Codable&lt;/li&gt;
&lt;li&gt;[] Should I be writing my own &lt;a href=&#34;https://en.wikipedia.org/wiki/ISO/IEC_8859-1&#34;&gt;&lt;code&gt;ISOLatin1String&lt;/code&gt;&lt;/a&gt; like what HTTPType has that uses &lt;code&gt;[UInt8]&lt;/code&gt; as a backing storage? String implementations in embedded are going to be very varied.&lt;/li&gt;
&lt;li&gt;[] this is all still blocking. how to use an interrupt based event loop if the sdk makes one available?&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;But back to what I was able to do. My current HTTP request gets managed by a &lt;a href=&#34;https://github.com/carlynorama/swift_esp32c6_hello/blob/90d8509be441c5abffe760bc21699522772ef161/components/http_bridge/http_bridge.c#L8&#34;&gt;whisper thin Swift wrapper around C&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;d like to make it a little less whisper thin.&lt;/p&gt;
&lt;p&gt;The results so far here:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/carlynorama/swift_esp32c6_hello/tree/e_ImproveHTTPClient&#34;&gt;https://github.com/carlynorama/swift_esp32c6_hello/tree/e_ImproveHTTPClient&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;setting-up-the-protocol&#34;&gt;Setting Up the Protocol&lt;/h2&gt;
&lt;p&gt;What&amp;rsquo;s my minimum viable client for the demo? Describe it as a protocol:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;protocol&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;HTTPClient&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#ed8796&#34;&gt;init&lt;/span&gt;(host: &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;, port:&lt;span style=&#34;color:#91d7e3&#34;&gt;Int&lt;/span&gt;?)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;fetch&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; path:&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;and a the client moves to an implementation.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;struct&lt;/span&gt;  &lt;span style=&#34;color:#eed49f&#34;&gt;ServerInfo&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//scheme is always http&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//let useHTTPS: Bool = true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;host&lt;/span&gt;:&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt; &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;TODO:&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt; will have to split to domain for dns lookup?&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;port&lt;/span&gt;:&lt;span style=&#34;color:#91d7e3&#34;&gt;Int&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//let basePath = String //future&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;final&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;MyClient&lt;/span&gt;: HTTPClient {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;defaultServer&lt;/span&gt;: ServerInfo
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;init&lt;/span&gt;(host: &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;, port: &lt;span style=&#34;color:#91d7e3&#34;&gt;Int&lt;/span&gt;? = &lt;span style=&#34;color:#f5a97f&#34;&gt;nil&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; port == &lt;span style=&#34;color:#f5a97f&#34;&gt;nil&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;.defaultServer = ServerInfo(host: host, port: &lt;span style=&#34;color:#f5a97f&#34;&gt;80&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    } &lt;span style=&#34;color:#c6a0f6&#34;&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;.defaultServer = ServerInfo(host: host, port: port!)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;In &lt;code&gt;Main.swift&lt;/code&gt; using the following instantiation would lock it down so the subsequent code can only use the features of the class that comply with the protocol.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;exampleClient&lt;/span&gt;: some HTTPClient = MyClient(host: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;example.com&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;I don&amp;rsquo;t love this. As noted in my TODO&amp;rsquo;s I&amp;rsquo;d prefer to have a concrete HTTPClient type that links to a HTTPClientService protocol instead, more like the way the momentary button code is &lt;a href=&#34;https://github.com/carlynorama/swift_esp32c6_hello/blob/e_ImproveHTTPClient/main/MomentaryInput.swift&#34;&gt;two steps away&lt;/a&gt; from the underlying hardware architecture.&lt;/p&gt;
&lt;p&gt;I am also on the fence about having a client be attached to a specific server.&lt;/p&gt;
&lt;h2 id=&#34;resolve-the-dns&#34;&gt;Resolve the DNS&lt;/h2&gt;
&lt;p&gt;To resolve the underlying DNS the standard trick is to use the c function &lt;a href=&#34;https://en.wikipedia.org/wiki/Getaddrinfo&#34;&gt;getaddrinfo&lt;/a&gt;, even &lt;a href=&#34;https://github.com/apple/swift-nio/blob/6c114e3c62ff84ef325d5071b42171d84b63e8a5/Sources/NIOPosix/GetaddrinfoResolver.swift#L21&#34;&gt;SwiftNIO&lt;/a&gt; uses it.&lt;/p&gt;
&lt;p&gt;It writes the result to a C struct which has another C struct embedded in it passed as a reference:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-C&#34; data-lang=&#34;C&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;struct&lt;/span&gt; addrinfo {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;int&lt;/span&gt;              ai_flags;     &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// AI_PASSIVE, AI_CANONNAME, etc.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;int&lt;/span&gt;              ai_family;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// AF_INET, AF_INET6, AF_UNSPEC
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;int&lt;/span&gt;              ai_socktype;  &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// SOCK_STREAM, SOCK_DGRAM
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;int&lt;/span&gt;              ai_protocol;  &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// use 0 for &amp;#34;any&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;size_t&lt;/span&gt;           ai_addrlen;   &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// size of ai_addr in bytes
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;struct&lt;/span&gt; sockaddr &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;*&lt;/span&gt;ai_addr;      &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// struct sockaddr_in or _in6
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;char&lt;/span&gt;            &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;*&lt;/span&gt;ai_canonname; &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// full canonical hostname
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;struct&lt;/span&gt; addrinfo &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;*&lt;/span&gt;ai_next;      &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// linked list, next node
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;};
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;struct&lt;/span&gt; sockaddr {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;unsigned&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;short&lt;/span&gt;    sa_family;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// address family, AF_xxx
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;char&lt;/span&gt;              sa_data[&lt;span style=&#34;color:#f5a97f&#34;&gt;14&lt;/span&gt;];  &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// 14 bytes of protocol address
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;}; 
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;For the time being I chose to hold that result container in a class level variable, making sure to have a deinit for it, just in case. I tried holding the pointee instead of the pointer, which appeared to work, but fell apart when creating the socket.&lt;/p&gt;
&lt;p&gt;I also hard coded a retry of 6 times, which a better library would let the developer config.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;enum&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;HTTPClientError&lt;/span&gt;: Error {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#c6a0f6&#34;&gt;case&lt;/span&gt; hostUnresolved
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;describe&lt;/span&gt;: &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;switch&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;case&lt;/span&gt; .hostUnresolved: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;hostUnresolved&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;final&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;MyClient&lt;/span&gt;: HTTPClient {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;internal&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;typealias&lt;/span&gt; AddressInfo = addrinfo
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;currentInfo&lt;/span&gt;: &lt;span style=&#34;color:#91d7e3&#34;&gt;UnsafeMutablePointer&lt;/span&gt;&amp;lt;addrinfo&amp;gt;?
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;defaultServer&lt;/span&gt;: ServerInfo
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;init&lt;/span&gt;(host: &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;, port: &lt;span style=&#34;color:#91d7e3&#34;&gt;Int&lt;/span&gt;? = &lt;span style=&#34;color:#f5a97f&#34;&gt;nil&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; port == &lt;span style=&#34;color:#f5a97f&#34;&gt;nil&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;.defaultServer = ServerInfo(host: host, port: &lt;span style=&#34;color:#f5a97f&#34;&gt;80&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        } &lt;span style=&#34;color:#c6a0f6&#34;&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;.defaultServer = ServerInfo(host: host, port: port!)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;TODO:&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt; what if i just nil&amp;#39;d it? &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;deinit&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;currentInfo&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            freeaddrinfo(currentInfo)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;test&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;resolving...&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#c6a0f6&#34;&gt;do&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; getAddressInfo(&lt;span style=&#34;color:#c6a0f6&#34;&gt;for&lt;/span&gt;: server.host, using: server.port)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      } &lt;span style=&#34;color:#c6a0f6&#34;&gt;catch&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;myError&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Error info: &lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;myError.describe&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;private&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;getAddressInfo&lt;/span&gt;(&lt;span style=&#34;color:#c6a0f6&#34;&gt;for&lt;/span&gt; host: &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;, using port: &lt;span style=&#34;color:#91d7e3&#34;&gt;Int&lt;/span&gt; = &lt;span style=&#34;color:#f5a97f&#34;&gt;80&lt;/span&gt;) &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt;(HTTPClientError) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        currentInfo = &lt;span style=&#34;color:#f5a97f&#34;&gt;nil&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;retry&lt;/span&gt; = &lt;span style=&#34;color:#f5a97f&#34;&gt;6&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;local_host&lt;/span&gt; = host.utf8CString
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;while&lt;/span&gt; retry &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;0&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;hints&lt;/span&gt;: AddressInfo = addrinfo()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        hints.ai_socktype = SOCK_STREAM  &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//vs SOCK_DGRAM&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        hints.ai_protocol = AF_INET  &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//IP version 4, vs 6 or unix&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;error&lt;/span&gt; = local_host.withContiguousStorageIfAvailable { host_name &lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; getaddrinfo(host_name.baseAddress, &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;port&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;, &amp;amp;hints, &amp;amp;currentInfo)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; error == &lt;span style=&#34;color:#f5a97f&#34;&gt;0&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;got it.&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            retry = &lt;span style=&#34;color:#f5a97f&#34;&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        } &lt;span style=&#34;color:#c6a0f6&#34;&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; error == &lt;span style=&#34;color:#f5a97f&#34;&gt;nil&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;why wasn&amp;#39;t contiguous storage available?&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            } &lt;span style=&#34;color:#c6a0f6&#34;&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;getAddressInfo error: &lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;error!&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            retry = retry &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;-&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        currentInfo = &lt;span style=&#34;color:#f5a97f&#34;&gt;nil&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;throw&lt;/span&gt; HTTPClientError.hostUnresolved
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;NOTE: I am having a problem that requires me to unplug and replug my board while the monitor is still running to get the host to resolve some of the time. I think this might be a &lt;a href=&#34;https://esp32.com/viewtopic.php?t=39714&#34;&gt;esp-idf DNS cache problem&lt;/a&gt;? It does not always happen.&lt;/p&gt;
&lt;h2 id=&#34;connect-the-socket&#34;&gt;Connect the socket&lt;/h2&gt;
&lt;p&gt;I again created a top level variable to hold an &amp;ldquo;open socket&amp;rdquo;. It&amp;rsquo;s just a &lt;code&gt;CInt&lt;/code&gt; that the underlying network code can use to locate which underlying hardware to use. Once a socket has been opened, it&amp;rsquo;s important to close it. Once a socket has been opened, this top level var should be returned to nil only after &lt;code&gt;close()&lt;/code&gt; has been called. This will let my code know if it has done proper clean up.&lt;/p&gt;
&lt;p&gt;The swift nio socket type:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/apple/swift-nio/blob/6c114e3c62ff84ef325d5071b42171d84b63e8a5/Sources/NIOPosix/BaseSocket.swift#L96&#34;&gt;https://github.com/apple/swift-nio/blob/6c114e3c62ff84ef325d5071b42171d84b63e8a5/Sources/NIOPosix/BaseSocket.swift#L96&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/apple/swift-nio/blob/6c114e3c62ff84ef325d5071b42171d84b63e8a5/Sources/NIOPosix/BSDSocketAPICommon.swift#L62&#34;&gt;https://github.com/apple/swift-nio/blob/6c114e3c62ff84ef325d5071b42171d84b63e8a5/Sources/NIOPosix/BSDSocketAPICommon.swift#L62&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;final&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;MyClient&lt;/span&gt;: HTTPClient {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#ed8796&#34;&gt;internal&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;typealias&lt;/span&gt; AddressInfo = addrinfo
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#ed8796&#34;&gt;internal&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;typealias&lt;/span&gt; SocketAddress = sockaddr
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#ed8796&#34;&gt;internal&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;typealias&lt;/span&gt; SocketHandle = &lt;span style=&#34;color:#91d7e3&#34;&gt;CInt&lt;/span&gt;  &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//none of the functions use socklen_t?&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;currentInfo&lt;/span&gt;: &lt;span style=&#34;color:#91d7e3&#34;&gt;UnsafeMutablePointer&lt;/span&gt;&amp;lt;AddressInfo&amp;gt;?
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;openSocket&lt;/span&gt;: SocketHandle?
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#ed8796&#34;&gt;deinit&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;openSocket&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      close(openSocket)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;currentInfo&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      freeaddrinfo(currentInfo)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;test&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;resolving...&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#c6a0f6&#34;&gt;do&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; getAddressInfo(&lt;span style=&#34;color:#c6a0f6&#34;&gt;for&lt;/span&gt;: server.host, using: server.port)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        openSocket = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; connectSocket()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        freeaddrinfo(currentInfo)  &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//addrinfo has a freshness value.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#91d7e3&#34;&gt;assert&lt;/span&gt;(currentInfo == &lt;span style=&#34;color:#f5a97f&#34;&gt;nil&lt;/span&gt;) &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//check to make sure that actually nil&amp;#39;d it too. &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      } &lt;span style=&#34;color:#c6a0f6&#34;&gt;catch&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;myError&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Error info: &lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;myError.describe&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;If the connection is successful, return the socket handle.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;private&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;connectSocket&lt;/span&gt;() &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt;(HTTPClientError) -&amp;gt; SocketHandle {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;currentInfo&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;I have AddressInfo&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;socket&lt;/span&gt;: SocketHandle = socket(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        currentInfo.pointee.ai_family, currentInfo.pointee.ai_socktype, &lt;span style=&#34;color:#f5a97f&#34;&gt;0&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; socket &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;lt;&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;0&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;throw&lt;/span&gt; HTTPClientError.couldNotMakeSocket
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;socketHandle: &lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;socket&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;retry&lt;/span&gt; = &lt;span style=&#34;color:#f5a97f&#34;&gt;6&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#c6a0f6&#34;&gt;while&lt;/span&gt; retry &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;0&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;connectValue&lt;/span&gt; = connect(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          socket, currentInfo.pointee.ai_addr, currentInfo.pointee.ai_addrlen)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; connectValue == &lt;span style=&#34;color:#f5a97f&#34;&gt;0&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          retry = &lt;span style=&#34;color:#f5a97f&#34;&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; socket
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        } &lt;span style=&#34;color:#c6a0f6&#34;&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;connect returned &lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;connectValue&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        delay(&lt;span style=&#34;color:#f5a97f&#34;&gt;500&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        retry = retry &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;-&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;retry connect &lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;retry&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      close(socket)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#c6a0f6&#34;&gt;throw&lt;/span&gt; HTTPClientError.connectionFailed
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;throw&lt;/span&gt; HTTPClientError.addressUnresolved
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;write-to-the-socket&#34;&gt;Write to the Socket&lt;/h2&gt;
&lt;p&gt;In a future version of this client I&amp;rsquo;d like to formulate a &lt;code&gt;HTTPRequest&lt;/code&gt; that gets handled to a ClientService that does the serialization, but for now it&amp;rsquo;s hand coded. Why are those &amp;ldquo;extra steps&amp;rdquo; a good idea? Well, because when dealing with protocols it&amp;rsquo;s &lt;a href=&#34;https://forums.swift.org/t/embedded-esp32c6-lightweight-c-wrapper-around-a-socket-having-trouble-formatting-request-bytes/82255&#34;&gt;REALLY REALLY easy to forget&lt;/a&gt; things like required terminating newlines, carriage returns, 0 and other final characters.&lt;/p&gt;
&lt;p&gt;It&amp;rsquo;s helpful to be able to see the request on the receiving side, but since this isn&amp;rsquo;t a client running on my machine, there are a couple extra steps to &lt;a href=&#34;https://whynotestflight.com/excuses/a-picture-takes-1000-words/#using-netcat&#34;&gt;troubleshooting with netcat&lt;/a&gt;. One has to turn off firewalls and use the &lt;code&gt;ifconfig&lt;/code&gt; command (look for &lt;code&gt;en0: &lt;/code&gt;). It&amp;rsquo;s likely to be an address like &lt;code&gt;192.168.42.***&lt;/code&gt; and then my client init would look like:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;exampleClient&lt;/span&gt;: some HTTPClient = MyClient(host: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;192.168.42.***&amp;#34;&lt;/span&gt;, port:&lt;span style=&#34;color:#f5a97f&#34;&gt;8080&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;(For an IP not on the same private network try something like &lt;a href=&#34;https://ifconfig.me&#34;&gt;ifconfig.me&lt;/a&gt;, but there&amp;rsquo;s a million of these sites.)&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;test&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;resolving...&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#c6a0f6&#34;&gt;do&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; getAddressInfo(&lt;span style=&#34;color:#c6a0f6&#34;&gt;for&lt;/span&gt;: server.host, using: server.port)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        openSocket = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; connectSocket()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        freeaddrinfo(currentInfo)  &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//addrinfo has a freshness value.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#91d7e3&#34;&gt;assert&lt;/span&gt;(currentInfo == &lt;span style=&#34;color:#f5a97f&#34;&gt;nil&lt;/span&gt;) &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//check to make sure that actually nil&amp;#39;d it too. &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; writeRequest(with: openSocket!, to: defaultServer.host, at: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;/&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      } &lt;span style=&#34;color:#c6a0f6&#34;&gt;catch&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;myError&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Error info: &lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;myError.describe&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;TODO:&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt; close socket if a socket related error? &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Notice my request type is a &lt;a href=&#34;https://developer.apple.com/documentation/swift/contiguousarray&#34;&gt;&lt;code&gt;ContiguousArray&amp;lt;CChar&amp;gt;&lt;/code&gt;&lt;/a&gt; and I&amp;rsquo;m still using that &lt;a href=&#34;https://developer.apple.com/documentation/swift/string/withcontiguousstorageifavailable(_:)&#34;&gt;&lt;code&gt;withContiguousStorageIfAvailable&lt;/code&gt;&lt;/a&gt; closure like in the &lt;a href=&#34;https://whynotestflight.com/excuses/can-i-make-a-swift-wrapped-http-get-request-from-the-esp32c6/#httpswift&#34;&gt;first pass at the client&lt;/a&gt;. C Strings are very different than Swift Strings and trying to pass a non-contiguous storage type  (Swift String) to a contiguous storage type (C String) will end up with all sorts of bad data reads, etc. Very. Unsafe.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#ed8796&#34;&gt;private&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;writeRequest&lt;/span&gt;(with socket: SocketHandle, to host: &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;, at path: &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt;(HTTPClientError)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//DON&amp;#39;T FORGET THE CLOSING \r\n&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;request&lt;/span&gt;: &lt;span style=&#34;color:#91d7e3&#34;&gt;ContiguousArray&lt;/span&gt;&amp;lt;&lt;span style=&#34;color:#91d7e3&#34;&gt;CChar&lt;/span&gt;&amp;gt; =
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;GET &lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;path&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt; HTTP/1.0&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\r\n&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;Host: &lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;host&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\r\n&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;User-Agent: &lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;userAgent&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\r\n\r\n&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;.utf8CString
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;request length: &lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;request.&lt;span style=&#34;color:#91d7e3&#34;&gt;count&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;request&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;result&lt;/span&gt; = request.withContiguousStorageIfAvailable { request_buffer &lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;writeResponse&lt;/span&gt; = write(socket, request_buffer.baseAddress, request_buffer.&lt;span style=&#34;color:#91d7e3&#34;&gt;count&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;writeResponse: &lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;writeResponse&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; writeResponse
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; result &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;!=&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;nil&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;amp;&amp;amp;&lt;/span&gt; result! &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;lt;&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;0&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      close(socket)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;.openSocket = &lt;span style=&#34;color:#f5a97f&#34;&gt;nil&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#c6a0f6&#34;&gt;throw&lt;/span&gt; HTTPClientError.sendFailed
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; result == &lt;span style=&#34;color:#f5a97f&#34;&gt;nil&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;what happened?&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//close socket? &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#c6a0f6&#34;&gt;throw&lt;/span&gt; HTTPClientError.unsendableRequest
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;listen&#34;&gt;Listen&lt;/h2&gt;
&lt;p&gt;This time I&amp;rsquo;ll show the function first because the return type is important, its a &lt;code&gt;[UInt8]&lt;/code&gt; that DOES NOT null terminate the buffer.  If this code was C the buffer would be a &lt;code&gt;char*&lt;/code&gt; with null termination. &lt;code&gt;char*&lt;/code&gt; becomes &lt;code&gt;[CChar]&lt;/code&gt; which comes into Swift as a &lt;code&gt;[Int8]&lt;/code&gt;. &lt;a href=&#34;https://forums.swift.org/t/any-plans-for-string-decoding-c-as-encoding-type-to-take-cchar-doesnt-seem-to-work-for-me/82337&#34;&gt;At the moment&lt;/a&gt;, far more &lt;code&gt;String&lt;/code&gt; initializers take a &lt;code&gt;[UInt8]&lt;/code&gt; than can accommodate the other two, including the initializer to the &lt;code&gt;ISOLatin1String&lt;/code&gt; type in &lt;code&gt;HTTPTypes&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;If I was going to keep response buffer stored in a &lt;code&gt;[CChar]&lt;/code&gt; I would have null terminated it to be consistent with how C stores strings. In fact the line to do so is commented out in the code below.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#ed8796&#34;&gt;private&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;listenForResponse&lt;/span&gt;() &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt;(HTTPClientError) -&amp;gt; [&lt;span style=&#34;color:#91d7e3&#34;&gt;UInt8&lt;/span&gt;] {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;message&lt;/span&gt;: [&lt;span style=&#34;color:#91d7e3&#34;&gt;UInt8&lt;/span&gt;] = []
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;buffer&lt;/span&gt;: [&lt;span style=&#34;color:#91d7e3&#34;&gt;UInt8&lt;/span&gt;] = &lt;span style=&#34;color:#91d7e3&#34;&gt;Array&lt;/span&gt;(repeating: &lt;span style=&#34;color:#f5a97f&#34;&gt;0&lt;/span&gt;, &lt;span style=&#34;color:#91d7e3&#34;&gt;count&lt;/span&gt;: &lt;span style=&#34;color:#f5a97f&#34;&gt;512&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;guard&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;openSocket&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#c6a0f6&#34;&gt;throw&lt;/span&gt; HTTPClientError.noSocketOpen
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;_&lt;/span&gt; = buffer.withContiguousMutableStorageIfAvailable { buffer &lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;r&lt;/span&gt;: &lt;span style=&#34;color:#91d7e3&#34;&gt;CInt&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#c6a0f6&#34;&gt;repeat&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        r = read(openSocket, buffer.baseAddress, buffer.&lt;span style=&#34;color:#91d7e3&#34;&gt;count&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;-&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;1&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;bytes read: &lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;r&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//this buffer could be holding data from a previous read with&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//a longer r. Only copy r bytes. &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        message.append(contentsOf: buffer.&lt;span style=&#34;color:#c6a0f6&#34;&gt;prefix&lt;/span&gt;(&lt;span style=&#34;color:#91d7e3&#34;&gt;Int&lt;/span&gt;(r)))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      } &lt;span style=&#34;color:#c6a0f6&#34;&gt;while&lt;/span&gt; r &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//done so close the socket. &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    close(openSocket)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;.openSocket = &lt;span style=&#34;color:#f5a97f&#34;&gt;nil&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//DO NOT NULL TERMINATE IF NOT USING CChar&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//message.append(0)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; message
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Decisions about the byte type is null termination change what in &lt;code&gt;String&lt;/code&gt; initializers are available. At the call site I&amp;rsquo;ve chosen to use &lt;code&gt;String(validating: response, as: UTF8.self)&lt;/code&gt;, which will return nil if the bytes aren&amp;rsquo;t all UTF8 codable characters.&lt;/p&gt;
&lt;p&gt;Since we have a &lt;code&gt;UInt8&lt;/code&gt; array, another choice would be &lt;code&gt;String(decoding: response, as: UTF8.self)&lt;/code&gt; which will replace invalid data with &lt;code&gt;&amp;quot;\u{FFFD}&amp;quot;&lt;/code&gt; (official &lt;a href=&#34;https://unicodeplus.com/U+FFFD&#34;&gt;replacement character&lt;/a&gt; of &lt;a href=&#34;https://en.wikipedia.org/wiki/Specials_(Unicode_block)&#34;&gt;the specials&lt;/a&gt;), but always return something.&lt;/p&gt;
&lt;p&gt;There are MANY String initializers, and MANY of them in Swift 6 are deprecated in favor of the above 2, so those will be the ones I&amp;rsquo;ll lean on the most in future code.&lt;/p&gt;
&lt;p&gt;Neither of the remaining two accept null terminated strings, and it seems like all the CString acceptors have been deprecated, so clipping off the 0 and passing it along seems like the best choice. But only to &lt;code&gt;validating&lt;/code&gt; because &lt;code&gt;decoding&lt;/code&gt; won&amp;rsquo;t &lt;a href=&#34;https://forums.swift.org/t/any-plans-for-string-decoding-c-as-encoding-type-to-take-cchar-doesnt-seem-to-work-for-me/82337&#34;&gt;work with a &lt;code&gt;[Char]&lt;/code&gt;&lt;/a&gt;. But there is maybe one remaining static function? Anyway, this all seems a bit in flux.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//the one remaining static function. &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;message7&lt;/span&gt; = &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;.decodeCString(response &lt;span style=&#34;color:#c6a0f6&#34;&gt;as&lt;/span&gt;! [&lt;span style=&#34;color:#91d7e3&#34;&gt;UTF8&lt;/span&gt;.CodeUnit], &lt;span style=&#34;color:#c6a0f6&#34;&gt;as&lt;/span&gt;: &lt;span style=&#34;color:#91d7e3&#34;&gt;UTF8&lt;/span&gt;.&lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;, repairingInvalidCodeUnits: &lt;span style=&#34;color:#f5a97f&#34;&gt;true&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The final &lt;code&gt;fetch&lt;/code&gt; function:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#ed8796&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;fetch&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; path: &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    fetch(path, from: defaultServer)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;fetch&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; path: &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;, from server: ServerInfo) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;do&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;resolving...&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; getAddressInfo(&lt;span style=&#34;color:#c6a0f6&#34;&gt;for&lt;/span&gt;: server.host, using: server.port)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;connecting...&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      openSocket = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; connectSocket()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      freeaddrinfo(currentInfo) 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#91d7e3&#34;&gt;assert&lt;/span&gt;(currentInfo == &lt;span style=&#34;color:#f5a97f&#34;&gt;nil&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;currentInfo is nil: &lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;currentInfo == &lt;span style=&#34;color:#f5a97f&#34;&gt;nil&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;writing...&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; writeRequest(with: openSocket!, to: defaultServer.host, at: path)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;listening...&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;response&lt;/span&gt; = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; getResponse()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//print(&amp;#34;response count: \(response.count)&amp;#34;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//for the future. &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//let message = ISOLatin1String(response) &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;message&lt;/span&gt; = &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;(validating: response, &lt;span style=&#34;color:#c6a0f6&#34;&gt;as&lt;/span&gt;: &lt;span style=&#34;color:#91d7e3&#34;&gt;UTF8&lt;/span&gt;.&lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;message was valid UTF8&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(message)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      } &lt;span style=&#34;color:#c6a0f6&#34;&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;message could not be decoded as UTF8&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;done&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    } &lt;span style=&#34;color:#c6a0f6&#34;&gt;catch&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;myError&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Error info: &lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;myError.describe&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;openSocket&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        close(openSocket)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;currentInfo&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        freeaddrinfo(currentInfo)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Running this code on the Xiao should spit out the full example.com home page!&lt;/p&gt;
&lt;h2 id=&#34;summary&#34;&gt;Summary&lt;/h2&gt;
&lt;p&gt;So still a lot left to do.  Even on top of all I want in that TODO list at the top, a bare minimum is to do enough parsing to tell what the status code is.&lt;/p&gt;
&lt;p&gt;That said, before I do that, I&amp;rsquo;ll probably take a look at the momentary button code so I can do this HTTP call &amp;ldquo;onPress&amp;rdquo; instead of on a timer.&lt;/p&gt;
</description>
    </item>
    
    
    
    <item>
      <title>Can I make my ESP32C6 HTTP client use HTTPTypes?</title>
      <link>https://whynotestflight.com/excuses/can-i-make-my-esp32c6-http-client-use-httptypes/</link>
      <pubDate>Tue, 23 Sep 2025 00:00:00 +0000</pubDate>
      
      <guid>https://whynotestflight.com/excuses/can-i-make-my-esp32c6-http-client-use-httptypes/</guid>
      <description>&lt;p&gt;So when &lt;a href=&#34;https://whynotestflight.com/excuses/can-i-make-a-swift-wrapped-http-get-request-from-the-esp32c6/&#34;&gt;we left off&lt;/a&gt; I had gotten the ESP32C6 to &lt;a href=&#34;https://github.com/carlynorama/swift_esp32c6_hello/tree/d_SimpleHTTPGet/main&#34;&gt;touch the internet&lt;/a&gt; using a very thin wrapper over C.&lt;/p&gt;
&lt;p&gt;The work for the next two posts can be seen on the &lt;a href=&#34;https://github.com/carlynorama/swift_esp32c6_hello/tree/e_ImproveHTTPClient&#34;&gt;e_ImproveHTTPClient&lt;/a&gt; branch.&lt;/p&gt;
&lt;p&gt;Reminder, in the terminal window, set up the environment if not using the VSCode extension.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;. &lt;span style=&#34;color:#f4dbd6&#34;&gt;$HOME&lt;/span&gt;/esp/esp-idf/export.sh
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#91d7e3&#34;&gt;cd&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;$PROJECT_FOLDER&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;idf.py set-target esp32c6
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# export SOME_PORT=`ls /dev/cu.usbmodem*`&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# echo $SOME_PORT&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;idf.py build
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;I thought it would be an interesting exercise to see what it would take to bring the code from the &lt;a href=&#34;https://github.com/apple/swift-http-types/&#34;&gt;HTTPTypes&lt;/a&gt; library into an embedded project.&lt;/p&gt;
&lt;p&gt;I copied all the files from the &lt;a href=&#34;https://github.com/apple/swift-http-types/tree/main/Sources/HTTPTypes&#34;&gt;core folder&lt;/a&gt; into a folder in my project and added them by hand to the CMake sources by hand:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-CMakeLists.txt&#34; data-lang=&#34;CMakeLists.txt&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# List of Swift source files to build.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#91d7e3&#34;&gt;target_sources&lt;/span&gt;(&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;${&lt;/span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;COMPONENT_LIB&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6da95&#34;&gt;PRIVATE&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6da95&#34;&gt;Main.swift&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6da95&#34;&gt;Bool_Int.swift&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6da95&#34;&gt;GPIOPin.swift&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6da95&#34;&gt;DigitalIndicator.swift&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6da95&#34;&gt;MomentaryInput.swift&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6da95&#34;&gt;Delay.swift&lt;/span&gt;     
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6da95&#34;&gt;ErrorHandler.swift&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6da95&#34;&gt;WiFi.swift&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6da95&#34;&gt;HTTP.swift&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6da95&#34;&gt;HTTPRevisedTypes/HTTPField.swift&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6da95&#34;&gt;HTTPRevisedTypes/HTTPFieldName.swift&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6da95&#34;&gt;HTTPRevisedTypes/HTTPFields.swift&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6da95&#34;&gt;HTTPRevisedTypes/HTTPParsedFields.swift&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6da95&#34;&gt;HTTPRevisedTypes/HTTPRequest.swift&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6da95&#34;&gt;HTTPRevisedTypes/HTTPResponse.swift&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6da95&#34;&gt;HTTPRevisedTypes/ISOLatin1String.swift&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6da95&#34;&gt;HTTPRevisedTypes/NIOLock.swift&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;)&lt;span style=&#34;color:#ed8796&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;I then got to work fixing all the compiler errors.  A lot of these are covered &lt;a href=&#34;https://docs.swift.org/embedded/documentation/embedded/basics&#34;&gt;in the Swift Embedded Examples Docs&lt;/a&gt; as caveats already.&lt;/p&gt;
&lt;h2 id=&#34;starting-easy&#34;&gt;Starting Easy&lt;/h2&gt;
&lt;p&gt;I&amp;rsquo;ve already been incredibly impressed how the esp-idf and Swift Embedded work together giving really nice String and print access with absolutely no work on my part, which is crazy. I&amp;rsquo;m not sure if people not coming from hardware development get how nice that is.&lt;/p&gt;
&lt;p&gt;So it&amp;rsquo;s not a surprise to me that I needed to strip out the following string mashing related features:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;conformances to &lt;code&gt;Codable&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;conformances to &lt;code&gt;CustomPlaygroundDisplayConvertible&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;all .description (only reaming one was in &lt;code&gt;CustomDebugStringConvertible&lt;/code&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I read that someone had gotten &lt;a href=&#34;https://forums.swift.org/t/an-embedded-audio-product-built-with-swift/77671/7&#34;&gt;Codable working maybe&lt;/a&gt;? but its pretty slow.  I ripped that all out without trying to get them to work.&lt;/p&gt;
&lt;h2 id=&#34;no-keypaths&#34;&gt;No KeyPaths&lt;/h2&gt;
&lt;p&gt;Also an easy fix was changing the map functions that use a &lt;a href=&#34;https://docs.swift.org/swift-book/documentation/the-swift-programming-language/expressions/#Key-Path-Expression&#34;&gt;KeyPath&lt;/a&gt; to actual closures. In HTTPFields.swift&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;subscript&lt;/span&gt;(values name: HTTPField.Name) -&amp;gt; [&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;] {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;get&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;.fields(&lt;span style=&#34;color:#c6a0f6&#34;&gt;for&lt;/span&gt;: name).&lt;span style=&#34;color:#91d7e3&#34;&gt;map&lt;/span&gt;(&lt;span style=&#34;color:#ed8796&#34;&gt;\&lt;/span&gt;.value)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;set&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;.setFields(newValue.&lt;span style=&#34;color:#c6a0f6&#34;&gt;lazy&lt;/span&gt;.&lt;span style=&#34;color:#91d7e3&#34;&gt;map&lt;/span&gt; { HTTPField(name: name, value: &lt;span style=&#34;color:#f4dbd6&#34;&gt;$0&lt;/span&gt;) }, &lt;span style=&#34;color:#c6a0f6&#34;&gt;for&lt;/span&gt;: name)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;becomes&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;subscript&lt;/span&gt;(values name: HTTPField.Name) -&amp;gt; [&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;] {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;get&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;.fields(&lt;span style=&#34;color:#c6a0f6&#34;&gt;for&lt;/span&gt;: name).&lt;span style=&#34;color:#91d7e3&#34;&gt;map&lt;/span&gt;({&lt;span style=&#34;color:#f4dbd6&#34;&gt;$0&lt;/span&gt;.value})
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;set&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;.setFields(newValue.&lt;span style=&#34;color:#c6a0f6&#34;&gt;lazy&lt;/span&gt;.&lt;span style=&#34;color:#91d7e3&#34;&gt;map&lt;/span&gt; { HTTPField(name: name, value: &lt;span style=&#34;color:#f4dbd6&#34;&gt;$0&lt;/span&gt;) }, &lt;span style=&#34;color:#c6a0f6&#34;&gt;for&lt;/span&gt;: name)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;clarifying-error-types&#34;&gt;Clarifying Error Types&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;HTTPParsedFields&lt;/code&gt; has a lot of throwing functions. They all need to be given an explicit Error type because &lt;code&gt;any Error&lt;/code&gt;, as an Existential is &lt;a href=&#34;https://docs.swift.org/embedded/documentation/embedded/existentials&#34;&gt;not allowed in embedded&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;From:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;private&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;validateFields&lt;/span&gt;() &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;guard&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;.fields[values: .contentLength].allElementsSame &lt;span style=&#34;color:#c6a0f6&#34;&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;throw&lt;/span&gt; ParsingError.multipleContentLength
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;guard&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;.fields[values: .contentDisposition].allElementsSame &lt;span style=&#34;color:#c6a0f6&#34;&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;throw&lt;/span&gt; ParsingError.multipleContentDisposition
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;guard&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;.fields[values: .location].allElementsSame &lt;span style=&#34;color:#c6a0f6&#34;&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;throw&lt;/span&gt; ParsingError.multipleLocation
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;extension&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;HTTPRequest&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;init&lt;/span&gt;(parsed fields: [HTTPField]) &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;parsedFields&lt;/span&gt; = HTTPParsedFields()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;for&lt;/span&gt; field &lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt; fields {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; parsedFields.add(field: field)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt; = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; parsedFields.request
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;To:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;private&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;validateFields&lt;/span&gt;() &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt;(ParsingError) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;guard&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;.fields[values: .contentLength].allElementsSame &lt;span style=&#34;color:#c6a0f6&#34;&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;throw&lt;/span&gt; ParsingError.multipleContentLength
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;guard&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;.fields[values: .contentDisposition].allElementsSame &lt;span style=&#34;color:#c6a0f6&#34;&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;throw&lt;/span&gt; ParsingError.multipleContentDisposition
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;guard&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;.fields[values: .location].allElementsSame &lt;span style=&#34;color:#c6a0f6&#34;&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;throw&lt;/span&gt; ParsingError.multipleLocation
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;extension&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;HTTPRequest&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;init&lt;/span&gt;(parsed fields: [HTTPField]) &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt;(HTTPParsedFields.ParsingError) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;parsedFields&lt;/span&gt; = HTTPParsedFields()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;for&lt;/span&gt; field &lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt; fields {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; parsedFields.add(field: field)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt; = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; parsedFields.request
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;the-doozey-httpfields-underlying-storage&#34;&gt;The Doozey: HTTPFields underlying storage.&lt;/h2&gt;
&lt;p&gt;So the biggest fanciest thing in HTTPTypes is the different locks but on the field storage to make them concurrency safe.&lt;/p&gt;
&lt;p&gt;There is a base class called &lt;a href=&#34;https://github.com/apple/swift-http-types/blob/b00139f252b2358367bc3fc4cecdb5f5d49947e7/Sources/HTTPTypes/HTTPFields.swift#L28&#34;&gt;_Storage&lt;/a&gt; that depending on the compiler information will pick one of two child classes: &lt;a href=&#34;https://github.com/apple/swift-http-types/blob/b00139f252b2358367bc3fc4cecdb5f5d49947e7/Sources/HTTPTypes/HTTPFields.swift#L114C25-L114C42&#34;&gt;_StorageWithMutex&lt;/a&gt; or &lt;a href=&#34;https://github.com/apple/swift-http-types/blob/b00139f252b2358367bc3fc4cecdb5f5d49947e7/Sources/HTTPTypes/HTTPFields.swift#L125C25-L125C44&#34;&gt;_StorageWithNIOLock&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Swift Embedded with the esp-idf version I&amp;rsquo;m using has no &lt;a href=&#34;https://developer.apple.com/documentation/synchronization/mutex&#34;&gt;&lt;code&gt;Mutex&lt;/code&gt;&lt;/a&gt; and &lt;a href=&#34;https://github.com/apple/swift-http-types/blob/main/Sources/HTTPTypes/NIOLock.swift&#34;&gt;NIOLock&lt;/a&gt; hit the &lt;a href=&#34;https://github.com/apple/swift-http-types/blob/b00139f252b2358367bc3fc4cecdb5f5d49947e7/Sources/HTTPTypes/NIOLock.swift#L45C1-L45C80&#34;&gt;&amp;ldquo;unable to identify C library&amp;rdquo;&lt;/a&gt; error.&lt;/p&gt;
&lt;p&gt;I could not add a child &lt;code&gt;_StorageForEmbedded&lt;/code&gt; because the parent a template for the two children to implement their competing lock strategies.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;withLock&lt;/span&gt;&amp;lt;Result&amp;gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; body: () &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; -&amp;gt; Result) &lt;span style=&#34;color:#c6a0f6&#34;&gt;rethrows&lt;/span&gt; -&amp;gt; Result {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#91d7e3&#34;&gt;fatalError&lt;/span&gt;()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ul&gt;
&lt;li&gt;swift:35:14: error: classes cannot have non-final generic functions in embedded Swift&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://docs.swift.org/embedded/documentation/embedded/nonfinalgenericmethods&#34;&gt;https://docs.swift.org/embedded/documentation/embedded/nonfinalgenericmethods&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;So options include:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;I could potentially write some kind of lock system using &lt;a href=&#34;https://en.wikipedia.org/wiki/Pthreads&#34;&gt;pthread&lt;/a&gt; and it is entirely possible that the espressif sdk already thought of that and I could just steal it. (They&amp;rsquo;ve got &lt;a href=&#34;https://docs.espressif.com/projects/esp-idf/en/v5.5.1/esp32c6/api-reference/system/esp_event.html&#34;&gt;an event system&lt;/a&gt; after all.)&lt;/li&gt;
&lt;li&gt;Then I could use it to write a child class of _Storage that uses it&amp;hellip;&lt;/li&gt;
&lt;li&gt;But then I&amp;rsquo;d still end up with the non-final generic problem&lt;/li&gt;
&lt;li&gt;and there wouldn&amp;rsquo;t be a great way to pass it in (because for every new piece of hardware new locking storage would have to be provided based on a compiler check of some sort which would make the library pretty hard to maintain.)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;So in the mean time I just ripped out all the locking. In my demo that should be fine.&lt;/p&gt;
&lt;h2 id=&#34;so-much-striiiiiiinnnngggg&#34;&gt;So Much STRIIIIIIINNNNGGGG.&lt;/h2&gt;
&lt;p&gt;So HTTPTypes is essentially a String handing library: comparing strings, parsing strings, inspecting strings.  So even when getting all that done there&amp;rsquo;s one last library that needs to be explicitly added to prevent errors about missing &lt;code&gt;_swift_stdlib&lt;/code&gt; types in during a build.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;/Users/&lt;span style=&#34;color:#f4dbd6&#34;&gt;$USER&lt;/span&gt;/.espressif/tools/riscv32-esp-elf/esp-14.2.0_20241119/riscv32-esp-elf/bin/../lib/gcc/riscv32-esp-elf/14.2.0/../../../../riscv32-esp-elf/bin/ld: main.elf: hidden symbol &lt;span style=&#34;color:#a6da95&#34;&gt;`&lt;/span&gt;_swift_stdlib_getNormData&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#39; isn&amp;#39;&lt;/span&gt;t defined
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Looking at the &lt;a href=&#34;https://docs.swift.org/embedded/documentation/embedded/strings/&#34;&gt;Strings&lt;/a&gt; page in the Embedded Swift docs, right there in the list is &lt;code&gt;getNormData&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;HTTPRevisedTypes&lt;/code&gt; wanted&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;getNormData&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;getComposition&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;getDecompositionEntry&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;nfd_decompositions&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;All of those can be found by &lt;a href=&#34;https://linuxhandbook.com/search-less-command/&#34;&gt;inspecting the suggested library&lt;/a&gt; with &lt;a href=&#34;https://en.wikipedia.org/wiki/Strings_(Unix)&#34;&gt;strings&lt;/a&gt; piped to &lt;a href=&#34;https://en.wikipedia.org/wiki/Less_(Unix)&#34;&gt;less&lt;/a&gt;&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#91d7e3&#34;&gt;cd&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;`&lt;/span&gt;swiftly use --print-location&lt;span style=&#34;color:#a6da95&#34;&gt;`&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# update to be the target arch you&amp;#39;re looking for&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#91d7e3&#34;&gt;cd&lt;/span&gt; usr/lib/swift/embedded/riscv32-none-none-eabi
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;strings libswiftUnicodeDataTables.a | less
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# inside less type&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# /$SEARCH_ITEM&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# to find the text, just q to exit. &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This is some serious special sauce and it can be added to the project via CMake with&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-CMake&#34; data-lang=&#34;CMake&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#91d7e3&#34;&gt;set&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;COMPILER_TARGET&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;riscv32-none-none-eabi&amp;#34;&lt;/span&gt;)&lt;span style=&#34;color:#ed8796&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#91d7e3&#34;&gt;find_program&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;SWIFTLY&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;swiftly&amp;#34;&lt;/span&gt;)&lt;span style=&#34;color:#ed8796&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#91d7e3&#34;&gt;IF&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;SWIFTLY&lt;/span&gt;)&lt;span style=&#34;color:#ed8796&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;&lt;/span&gt;  &lt;span style=&#34;color:#91d7e3&#34;&gt;execute_process&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;COMMAND&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;swiftly&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;use&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;--print-location&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;OUTPUT_VARIABLE&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;toolchain_path&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;OUTPUT_STRIP_TRAILING_WHITESPACE&lt;/span&gt;)&lt;span style=&#34;color:#ed8796&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;&lt;/span&gt;  &lt;span style=&#34;color:#91d7e3&#34;&gt;cmake_path&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;SET&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;additional_lib_path&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;NORMALIZE&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;${toolchain_path}/usr/lib/swift/embedded/${COMPILER_TARGET}&amp;#34;&lt;/span&gt;)&lt;span style=&#34;color:#ed8796&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#91d7e3&#34;&gt;ELSE&lt;/span&gt;()&lt;span style=&#34;color:#ed8796&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;&lt;/span&gt;  &lt;span style=&#34;color:#91d7e3&#34;&gt;get_filename_component&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;compiler_bin_dir&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;${&lt;/span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;CMAKE_Swift_COMPILER&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;}&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;DIRECTORY&lt;/span&gt;)&lt;span style=&#34;color:#ed8796&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;&lt;/span&gt;  &lt;span style=&#34;color:#91d7e3&#34;&gt;cmake_path&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;SET&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;additional_lib_path&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;NORMALIZE&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;${compiler_bin_dir}/../lib/swift/embedded/${COMPILER_TARGET}&amp;#34;&lt;/span&gt;)&lt;span style=&#34;color:#ed8796&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#91d7e3&#34;&gt;ENDIF&lt;/span&gt;()&lt;span style=&#34;color:#ed8796&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#91d7e3&#34;&gt;target_link_directories&lt;/span&gt;(&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;${&lt;/span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;COMPONENT_LIB&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;}&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;PUBLIC&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;${additional_lib_path}&amp;#34;&lt;/span&gt;)&lt;span style=&#34;color:#ed8796&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#91d7e3&#34;&gt;target_link_libraries&lt;/span&gt;(&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;${&lt;/span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;COMPONENT_LIB&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6da95&#34;&gt;-Wl,--whole-archive&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6da95&#34;&gt;swiftUnicodeDataTables&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6da95&#34;&gt;-Wl,--no-whole-archive&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    )&lt;span style=&#34;color:#ed8796&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## debug message
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#91d7e3&#34;&gt;message&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34; ----------::: ${additional_lib_path} :::---------- &amp;#34;&lt;/span&gt;)&lt;span style=&#34;color:#ed8796&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;minimal-test&#34;&gt;Minimal Test&lt;/h2&gt;
&lt;p&gt;So&amp;hellip; it compiles now, but can it see the types?&lt;/p&gt;
&lt;p&gt;Adding a very minimal test&lt;/p&gt;
&lt;h3 id=&#34;httpswift&#34;&gt;HTTP.swift&lt;/h3&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;final&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;HTTPClient&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;test&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;request&lt;/span&gt; = HTTPRequest(method: .&lt;span style=&#34;color:#c6a0f6&#34;&gt;get&lt;/span&gt;, scheme: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;https&amp;#34;&lt;/span&gt;, authority: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;www.example.com&amp;#34;&lt;/span&gt;, path: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;/&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(request.scheme ?? &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;no scheme&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//....&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;mainswift&#34;&gt;Main.swift&lt;/h3&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//Waiting for wifi to connect...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  delay(&lt;span style=&#34;color:#f5a97f&#34;&gt;2000&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;client&lt;/span&gt; = HTTPClient()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  client.getAndPrint(from: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;example.com&amp;#34;&lt;/span&gt;, route: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;/&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  client.test()
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And that at least worked?&lt;/p&gt;
&lt;h2 id=&#34;can-httprevisedtypes-be-a-library&#34;&gt;Can HTTPRevisedTypes be a Library?&lt;/h2&gt;
&lt;p&gt;I have aspirations to be able to work with both the &lt;a href=&#34;https://www.espressif.com/en/products/software/esp-sdk/overview&#34;&gt;espressif sdk&lt;/a&gt; and the &lt;a href=&#34;https://github.com/carlynorama/swift-pico-w-hello&#34;&gt;pico-sdk&lt;/a&gt; better than I can now. Specifically, I want to be able to compartmentalize code into libraries via CMake since both of those SDKs use it. I can when writing &lt;a href=&#34;https://github.com/carlynorama/another-swift-cmake-examples&#34;&gt;my own simple examples&lt;/a&gt;, but not when meshing with C based SDK&amp;rsquo;s.&lt;/p&gt;
&lt;p&gt;As it is I tried a few different ways to change the &lt;code&gt;HTTPRevisedTypes&lt;/code&gt; files into a included library, all of which failed for various reasons related to my general CMake weaknesses, not understanding some of what the esp-idf is doing under the hood to piece projects together, and Swift embedded&amp;rsquo;s relying on &lt;a href=&#34;https://cmake.org/cmake/help/latest/variable/CMAKE_Swift_COMPILATION_MODE.html#variable:CMAKE_Swift_COMPILATION_MODE&#34;&gt;wholemodule mode&lt;/a&gt;, or maybe even the version of CMake that esp-idf 5.5 uses? I&amp;rsquo;m a few steps too low on the ladder to reach it yet.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://crascit.com/professional-cmake/&#34;&gt;I bought a book&lt;/a&gt;, but here is some additional reading to do.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://docs.espressif.com/projects/esp-idf/en/latest/esp32c6/api-guides/build-system.html&#34;&gt;https://docs.espressif.com/projects/esp-idf/en/latest/esp32c6/api-guides/build-system.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;digging around in &lt;code&gt;$HOME/esp/esp-idf/tools/&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://docs.espressif.com/projects/esp-idf/en/latest/esp32c6/migration-guides/release-5.x/5.0/build-system.html&#34;&gt;https://docs.espressif.com/projects/esp-idf/en/latest/esp32c6/migration-guides/release-5.x/5.0/build-system.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://docs.espressif.com/projects/esp-idf/en/latest/esp32c6/api-guides/build-system.html#writing-pure-cmake-components&#34;&gt;https://docs.espressif.com/projects/esp-idf/en/latest/esp32c6/api-guides/build-system.html#writing-pure-cmake-components&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/espressif/esp-idf/tree/166269fb9338607aa9726ecc4ea2d1763de31f0e/examples/build_system/cmake&#34;&gt;https://github.com/espressif/esp-idf/tree/166269fb9338607aa9726ecc4ea2d1763de31f0e/examples/build_system/cmake&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/espressif/esp-idf/blob/166269fb9338607aa9726ecc4ea2d1763de31f0e/examples/build_system/cmake/import_lib/components/tinyxml2/CMakeLists.txt&#34;&gt;https://github.com/espressif/esp-idf/blob/166269fb9338607aa9726ecc4ea2d1763de31f0e/examples/build_system/cmake/import_lib/components/tinyxml2/CMakeLists.txt&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;It seems like there is a path forward treating &lt;code&gt;HTTPRevisedTypes&lt;/code&gt; &lt;a href=&#34;https://docs.espressif.com/projects/esp-idf/en/latest/esp32c6/api-guides/build-system.html#cmake-component-properties&#34;&gt;as a component&lt;/a&gt;, but I&amp;rsquo;m not confident how that will interact with the Swift requirements and that keeps it chained to the esp-idf. In the future I might give it a shot since it can be done as &lt;a href=&#34;https://docs.espressif.com/projects/esp-idf/en/latest/esp32c6/api-guides/build-system.html#writing-pure-cmake-components&#34;&gt;pure CMake&lt;/a&gt;?&lt;/p&gt;
&lt;p&gt;In the mean time I want to focus on the client API, which could eventually use the request type under the hood.&lt;/p&gt;
</description>
    </item>
    
    
    
    <item>
      <title>How do I make a OpenAPI ClownAPI for Hummingbird?</title>
      <link>https://whynotestflight.com/excuses/how-do-i-make-a-openapi-clownapi-for-hummingbird/</link>
      <pubDate>Mon, 22 Sep 2025 00:00:00 +0000</pubDate>
      
      <guid>https://whynotestflight.com/excuses/how-do-i-make-a-openapi-clownapi-for-hummingbird/</guid>
      <description>&lt;p&gt;So now to expand out the full Clown CRUD and the updated tests. This post doesn&amp;rsquo;t review everything that can be seen in the &lt;a href=&#34;https://github.com/carlynorama/HummingbirdExamples/tree/main/06_helloOpenAPI&#34;&gt;repo example&lt;/a&gt;, but aspects of what it took to get there.&lt;/p&gt;
&lt;h2 id=&#34;what-response-codes-should-i-use&#34;&gt;What Response Codes should I use?&lt;/h2&gt;
&lt;p&gt;When designing an API, follow code conventions! But WHICH code conventions. I&amp;rsquo;ll swing back around to this topic again perhaps. I&amp;rsquo;m bringing it up now mostly to say that I didn&amp;rsquo;t focus on picking the perfect codes for this API.  I was focused on understanding how the OpenAPI spec and the generated code work, not writing the perfect API with it. Here are some references for future me when I do care.&lt;/p&gt;
&lt;p&gt;Some links&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://www.rfc-editor.org/rfc/rfc2616&#34;&gt;https://www.rfc-editor.org/rfc/rfc2616&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://en.wikipedia.org/wiki/List_of_HTTP_status_codes&#34;&gt;https://en.wikipedia.org/wiki/List_of_HTTP_status_codes&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Status/&#34;&gt;https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Status/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://apihandyman.io/empty-lists-http-status-code-200-vs-204-vs-404/&#34;&gt;https://apihandyman.io/empty-lists-http-status-code-200-vs-204-vs-404/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://apihandyman.io/hands-off-that-resource-http-status-code-401-vs-403-vs-404/&#34;&gt;https://apihandyman.io/hands-off-that-resource-http-status-code-401-vs-403-vs-404/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;using-the-server-section&#34;&gt;Using the Server Section&lt;/h2&gt;
&lt;p&gt;Added to &lt;a href=&#34;https://github.com/carlynorama/HummingbirdExamples/blob/main/06_openAPI/helloOpenAPI/Sources/ClownAPI/openapi.yaml&#34;&gt;my example&lt;/a&gt; is a server section:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://learn.openapis.org/specification/servers.html&#34;&gt;https://learn.openapis.org/specification/servers.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://swagger.io/docs/specification/v3_0/api-host-and-base-path/&#34;&gt;https://swagger.io/docs/specification/v3_0/api-host-and-base-path/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-yaml&#34; data-lang=&#34;yaml&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;servers&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  - &lt;span style=&#34;color:#c6a0f6&#34;&gt;url&lt;/span&gt;: http://localhost:{port}{basePath}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;description&lt;/span&gt;: Local Testing
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;variables&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#c6a0f6&#34;&gt;port&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;enum&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          - &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;8080&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          - &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;2525&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;default&lt;/span&gt;: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;8080&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#c6a0f6&#34;&gt;basePath&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;default&lt;/span&gt;: /api/v0/clowns
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;I haven&amp;rsquo;t yet configured it to work with multiple servers, but it means that I can query the API for what the endpoint base route should be. In this example I chose to fail gracefully if the API endpoints didn&amp;rsquo;t register. That makes more sense when the server is handling lots of types of routes.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;repository&lt;/span&gt; = ClownCar()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;clown_api&lt;/span&gt; = ClownAPIHandler(repository: repository)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;do&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(&lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; Servers.Server1.url())
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;url&lt;/span&gt; = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; Servers.Server1.url()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// like a addRote&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; clown_api.registerHandlers(on: router, serverURL: url) 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    } &lt;span style=&#34;color:#c6a0f6&#34;&gt;catch&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//handle this situation. &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;hello api failed to register. Those endpoints will not be available.&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;I added that same base route as static var to test against in my tests.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  @Suite(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;ClownAPITests&amp;#34;&lt;/span&gt;) &lt;span style=&#34;color:#ed8796&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;ClownAPITests&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;APIBase&lt;/span&gt; = &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;/api/v0/clowns&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;schema&#34;&gt;Schema&lt;/h2&gt;
&lt;p&gt;Open API can really nail down what the acceptable data should be for any type of request or response by specifying a by specifying a schema object.  Here are two simple examples with two different schemas, one for a plain text response, and one that shows an extremely basic JSON response.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://swagger.io/specification/#schema-object&#34;&gt;https://swagger.io/specification/#schema-object&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-yaml&#34; data-lang=&#34;yaml&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;/hello&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;get&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#c6a0f6&#34;&gt;operationId&lt;/span&gt;: greet
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#c6a0f6&#34;&gt;responses&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;&amp;#39;200&amp;#39;&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#c6a0f6&#34;&gt;description&lt;/span&gt;: A hello message as a string
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#c6a0f6&#34;&gt;content&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;text/plain&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;              &lt;span style=&#34;color:#c6a0f6&#34;&gt;schema&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#c6a0f6&#34;&gt;type&lt;/span&gt;: string
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#c6a0f6&#34;&gt;/helloworld&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;get&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#c6a0f6&#34;&gt;operationId&lt;/span&gt;: greetFormally
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#c6a0f6&#34;&gt;responses&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;&amp;#34;200&amp;#34;: &lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# When the request is successful&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#c6a0f6&#34;&gt;description&lt;/span&gt;: A JSON formatted hello message
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#c6a0f6&#34;&gt;content&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;application/json&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;              &lt;span style=&#34;color:#c6a0f6&#34;&gt;schema&lt;/span&gt;: &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# The returned JSON object&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#c6a0f6&#34;&gt;type&lt;/span&gt;: object
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#c6a0f6&#34;&gt;properties&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                  &lt;span style=&#34;color:#c6a0f6&#34;&gt;message&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    &lt;span style=&#34;color:#c6a0f6&#34;&gt;type&lt;/span&gt;: string
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#c6a0f6&#34;&gt;required&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                  - message
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Once again showing how to write this call the long way:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;greet&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; input: Operations.Greet.Input) async &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; -&amp;gt; Operations.Greet.Output {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//same as:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//return .ok(.init(body: .plainText(&amp;#34;Hello!&amp;#34;)))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;message&lt;/span&gt; = &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Hello&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;httpBody&lt;/span&gt; = OpenAPIRuntime.HTTPBody(message.utf8)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;OkBody&lt;/span&gt; = Operations.Greet.Output.Ok.Body.plainText(httpBody)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;greetOk&lt;/span&gt; = Operations.Greet.Output.Ok(body: OkBody)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;greetOutput&lt;/span&gt; = Operations.Greet.Output.ok(greetOk)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; greetOutput
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;greetFormally&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; input: Operations.GreetFormally.Input) async &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; -&amp;gt; Operations.GreetFormally.Output {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//same as:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// return .ok(.init(body:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//    .json(.init(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//        message: &amp;#34;Hello, world!&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//    ))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;jsonPayload&lt;/span&gt; = Operations.GreetFormally.Output.Ok.Body.JsonPayload(message: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Hello, world!&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;gfOkBody&lt;/span&gt; = Operations.GreetFormally.Output.Ok.Body.json(jsonPayload)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;gfOk&lt;/span&gt; = Operations.GreetFormally.Output.Ok(body: gfOkBody)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;gfOutput&lt;/span&gt; = Operations.GreetFormally.Output.ok(gfOk)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; greetFormallyOutput
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;referenced-schema&#34;&gt;Referenced Schema&lt;/h2&gt;
&lt;p&gt;Schema objects can be referenced, even in &lt;a href=&#34;https://stackoverflow.com/questions/71121399/how-do-i-incorporate-json-schema-into-my-openapi-file&#34;&gt;external files&lt;/a&gt;!&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://json-schema.org/blog/posts/validating-openapi-and-json-schema&#34;&gt;https://json-schema.org/blog/posts/validating-openapi-and-json-schema&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://www.speakeasy.com/openapi/schemas&#34;&gt;https://www.speakeasy.com/openapi/schemas&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://swagger.io/docs/specification/v3_0/data-models/data-models/&#34;&gt;https://swagger.io/docs/specification/v3_0/data-models/data-models/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://json-schema.org&#34;&gt;https://json-schema.org&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Since I&amp;rsquo;m likely to be using Clown&amp;rsquo;s a lot, at the bottom of the YAML I can put:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-yaml&#34; data-lang=&#34;yaml&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;components&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#c6a0f6&#34;&gt;schemas&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#   let id: Int&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#   var name: String&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#   var spareNoses: Int&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;Clown&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#c6a0f6&#34;&gt;type&lt;/span&gt;: object
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#c6a0f6&#34;&gt;description&lt;/span&gt;: A single clown profile.
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#c6a0f6&#34;&gt;properties&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;id&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#c6a0f6&#34;&gt;type&lt;/span&gt;: integer
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;name&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#c6a0f6&#34;&gt;type&lt;/span&gt;: string
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;spareNoses&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#c6a0f6&#34;&gt;type&lt;/span&gt;: integer
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#c6a0f6&#34;&gt;required&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        - id
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        - spareNoses
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        - name
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# other schemas...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The schema type lives inside the &lt;code&gt;Types.swift&lt;/code&gt; as a &lt;code&gt;Components.Schemas.Clown&lt;/code&gt;. I can make my life easier by adding an initializer to it that takes one of my local &lt;code&gt;Clown&lt;/code&gt; types.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;extension&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;Components&lt;/span&gt;.Schemas.Clown {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;/// Maps a `Clown` to a `Components.Schemas.Clown`&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;/// This makes it easier to send models to the API&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;init&lt;/span&gt;(clown: Clown) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;.&lt;span style=&#34;color:#ed8796&#34;&gt;init&lt;/span&gt;(id: clown.id, name: clown.name, spareNoses: clown.spareNoses)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Then I can make a route that depends on it:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-yaml&#34; data-lang=&#34;yaml&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#c6a0f6&#34;&gt;/test_clown&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# GET /test_clown&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;get&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#c6a0f6&#34;&gt;operationId&lt;/span&gt;: testClown
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#c6a0f6&#34;&gt;responses&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;&amp;#34;200&amp;#34;: &lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# When the request is successful&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#c6a0f6&#34;&gt;description&lt;/span&gt;: A basic clown profile.
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#c6a0f6&#34;&gt;content&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;application/json&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;              &lt;span style=&#34;color:#c6a0f6&#34;&gt;schema&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#c6a0f6&#34;&gt;$ref&lt;/span&gt;: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;#/components/schemas/Clown&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;My handler that needs to return that clown has a &lt;code&gt;.json&lt;/code&gt; output type that expects an instance of &lt;code&gt;Components.Schemas.Clown&lt;/code&gt; at its initialization.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;testClown&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; input:Operations.TestClown.Input) async &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; -&amp;gt; Operations.TestClown.Output {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;clown&lt;/span&gt; = Clown(id: &lt;span style=&#34;color:#f5a97f&#34;&gt;144214&lt;/span&gt;, name:&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Polka Dot&amp;#34;&lt;/span&gt; , spareNoses: &lt;span style=&#34;color:#f5a97f&#34;&gt;56&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//see extension above.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;myClown&lt;/span&gt; = Components.Schemas.Clown(clown: clown)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; .ok(.&lt;span style=&#34;color:#ed8796&#34;&gt;init&lt;/span&gt;(body: .json(myClown)))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// same as:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//return .ok(.init(body: .json(.init(clown:clown))))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;more-than-one-response-type&#34;&gt;More than one response type&lt;/h3&gt;
&lt;p&gt;Endpoints can have more than one response type, one per HTTP Response code.&lt;/p&gt;
&lt;p&gt;A kind of weak example is the current state of the delete function. Based on various conditions it will either return the clown just deleted or a &lt;code&gt;.badRequest&lt;/code&gt; type.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-yaml&#34; data-lang=&#34;yaml&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;delete&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#c6a0f6&#34;&gt;operationId&lt;/span&gt;: delete
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#c6a0f6&#34;&gt;parameters&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        - &lt;span style=&#34;color:#c6a0f6&#34;&gt;name&lt;/span&gt;: id
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt;: path
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#c6a0f6&#34;&gt;description&lt;/span&gt;: Clown ID
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#c6a0f6&#34;&gt;required&lt;/span&gt;: &lt;span style=&#34;color:#f5a97f&#34;&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#c6a0f6&#34;&gt;schema&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;type&lt;/span&gt;: integer
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#c6a0f6&#34;&gt;responses&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;200&amp;#34;&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#c6a0f6&#34;&gt;description&lt;/span&gt;: Successfully deleted the clown returned.
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#c6a0f6&#34;&gt;content&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;application/json&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;              &lt;span style=&#34;color:#c6a0f6&#34;&gt;schema&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#c6a0f6&#34;&gt;$ref&lt;/span&gt;: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;#/components/schemas/Clown&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;400&amp;#34;&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#c6a0f6&#34;&gt;description&lt;/span&gt;: Was not able to delete the clown or clown already did not exist.
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#c6a0f6&#34;&gt;content&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;text/plain&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;              &lt;span style=&#34;color:#c6a0f6&#34;&gt;schema&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#c6a0f6&#34;&gt;type&lt;/span&gt;: string
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;delete&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; input: Operations.Delete.Input) async &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; -&amp;gt; Operations.Delete.Output {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;id&lt;/span&gt; = input.path.id
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;clown&lt;/span&gt; = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; await repository.&lt;span style=&#34;color:#c6a0f6&#34;&gt;get&lt;/span&gt;(id: input.path.id) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; await &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;.repository.delete(id: id) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; .ok(.&lt;span style=&#34;color:#ed8796&#34;&gt;init&lt;/span&gt;(body: .json(.&lt;span style=&#34;color:#ed8796&#34;&gt;init&lt;/span&gt;(clown:clown))))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            } &lt;span style=&#34;color:#c6a0f6&#34;&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//Not. &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; .badRequest(.&lt;span style=&#34;color:#ed8796&#34;&gt;init&lt;/span&gt;(body: .plainText(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;id unable to be deleted.&amp;#34;&lt;/span&gt;)))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        } &lt;span style=&#34;color:#c6a0f6&#34;&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//perhaps a security leak, but okay. &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// this also may actually debatably be a success, in that this clown isn&amp;#39;t in the DB any more. Consider a 204.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; .badRequest(.&lt;span style=&#34;color:#ed8796&#34;&gt;init&lt;/span&gt;(body: .plainText(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;id already does not exist.&amp;#34;&lt;/span&gt;)))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        } 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;For 4XX and 5XX responses, consider including a &lt;a href=&#34;https://www.rfc-editor.org/rfc/rfc9457.html&#34;&gt;Problem JSON&lt;/a&gt; type for actual production schemas.&lt;/p&gt;
&lt;h2 id=&#34;undocumented-paths&#34;&gt;Undocumented Paths&lt;/h2&gt;
&lt;p&gt;The generator does give every handler an escape valve with &lt;code&gt;.undocumented&lt;/code&gt; outputs.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;greetFormally&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; input: Operations.GreetFormally.Input) async &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; -&amp;gt; Operations.GreetFormally.Output {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//undocumented(statusCode: Swift.Int, OpenAPIRuntime.UndocumentedPayload)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;message&lt;/span&gt; = &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Not right now thanks.&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;httpBody&lt;/span&gt; = OpenAPIRuntime.HTTPBody(message.utf8)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; .undocumented(statusCode: &lt;span style=&#34;color:#f5a97f&#34;&gt;418&lt;/span&gt;, .&lt;span style=&#34;color:#ed8796&#34;&gt;init&lt;/span&gt;(headerFields: .&lt;span style=&#34;color:#ed8796&#34;&gt;init&lt;/span&gt;(dictionaryLiteral: []), body: httpBody))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Use sparingly, if at all.&lt;/p&gt;
&lt;h2 id=&#34;using-an-input-type&#34;&gt;Using an Input Type&lt;/h2&gt;
&lt;p&gt;Inputs have generated types as well.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-yaml&#34; data-lang=&#34;yaml&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;post&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#c6a0f6&#34;&gt;operationId&lt;/span&gt;: create
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#c6a0f6&#34;&gt;requestBody&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;description&lt;/span&gt;: a clown to create
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;required&lt;/span&gt;: &lt;span style=&#34;color:#f5a97f&#34;&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;content&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#c6a0f6&#34;&gt;application/json&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;schema&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;              &lt;span style=&#34;color:#c6a0f6&#34;&gt;$ref&lt;/span&gt;: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;#/components/schemas/ClownCreateRequest&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#c6a0f6&#34;&gt;responses&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;200&amp;#34;&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#c6a0f6&#34;&gt;description&lt;/span&gt;: Successful creation with the clown returned.
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#c6a0f6&#34;&gt;content&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;application/json&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;              &lt;span style=&#34;color:#c6a0f6&#34;&gt;schema&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#c6a0f6&#34;&gt;$ref&lt;/span&gt;: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;#/components/schemas/Clown&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;201&amp;#34;&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#c6a0f6&#34;&gt;description&lt;/span&gt;: Successful creation with the id number returned
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#c6a0f6&#34;&gt;content&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;application/json&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;              &lt;span style=&#34;color:#c6a0f6&#34;&gt;schema&lt;/span&gt;: &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# The returned JSON object&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#c6a0f6&#34;&gt;type&lt;/span&gt;: object
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#c6a0f6&#34;&gt;properties&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                  &lt;span style=&#34;color:#c6a0f6&#34;&gt;id&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    &lt;span style=&#34;color:#c6a0f6&#34;&gt;type&lt;/span&gt;: integer
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#c6a0f6&#34;&gt;required&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                  - id
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;204&amp;#34;&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#c6a0f6&#34;&gt;description&lt;/span&gt;: Successful creation with empty body
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;400&amp;#34;&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#c6a0f6&#34;&gt;description&lt;/span&gt;: Some bad request. 
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The clown create request isn&amp;rsquo;t a Clown, but what&amp;rsquo;s wanted to create a clown. Only the &lt;code&gt;name&lt;/code&gt; is required.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-YAML&#34; data-lang=&#34;YAML&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;ClownCreateRequest&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#c6a0f6&#34;&gt;type&lt;/span&gt;: object
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#c6a0f6&#34;&gt;description&lt;/span&gt;: Fields to try to create a clown from.
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#c6a0f6&#34;&gt;properties&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;name&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#c6a0f6&#34;&gt;type&lt;/span&gt;: string
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;spareNoses&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#c6a0f6&#34;&gt;type&lt;/span&gt;: integer
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#c6a0f6&#34;&gt;required&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        - name
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;create&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; input:Operations.Create.Input) async &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; -&amp;gt; Operations.Create.Output {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;CREATING!!!&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//ClownCreateRequest&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; (name, suggestedNoses) = &lt;span style=&#34;color:#c6a0f6&#34;&gt;switch&lt;/span&gt; input.body {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;case&lt;/span&gt; .json(&lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;clownInfo&lt;/span&gt;):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                (clownInfo.name, clownInfo.spareNoses)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(name, suggestedNoses ?? &lt;span style=&#34;color:#f5a97f&#34;&gt;0&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;clown&lt;/span&gt; = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; await repository.create(name: name, spareNoses: suggestedNoses ?? &lt;span style=&#34;color:#f5a97f&#34;&gt;5&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; .ok(.&lt;span style=&#34;color:#ed8796&#34;&gt;init&lt;/span&gt;(body: .json(.&lt;span style=&#34;color:#ed8796&#34;&gt;init&lt;/span&gt;(clown: clown))))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;changes-to-the-tests&#34;&gt;Changes To The Tests&lt;/h2&gt;
&lt;p&gt;Most of the tests remain largely the same, but what to expect on the unhappy paths had to be updated.&lt;/p&gt;
&lt;p&gt;My &lt;code&gt;nil == 204&lt;/code&gt; problem can gets &amp;ldquo;fixed&amp;rdquo; in OpenAPI because returning a &lt;code&gt;Clown?&lt;/code&gt; just isn&amp;rsquo;t a thing one can do.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;fetchByID&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; input:Operations.FetchByID.Input) async &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; -&amp;gt; Operations.FetchByID.Output {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;clown&lt;/span&gt; = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; await repository.&lt;span style=&#34;color:#c6a0f6&#34;&gt;get&lt;/span&gt;(id: input.path.id) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; .ok(.&lt;span style=&#34;color:#ed8796&#34;&gt;init&lt;/span&gt;(body: .json(.&lt;span style=&#34;color:#ed8796&#34;&gt;init&lt;/span&gt;(clown:clown))))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        } &lt;span style=&#34;color:#c6a0f6&#34;&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; .notFound(.&lt;span style=&#34;color:#ed8796&#34;&gt;init&lt;/span&gt;(body: .plainText(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Was not able to retrieve that clown.&amp;#34;&lt;/span&gt;)))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;My one real beef with OpenAPI is how it &lt;a href=&#34;https://forums.swift.org/t/openapi-trying-to-use-soar-0011-errorhandlingmiddleware/&#34;&gt;handles Decoding errors&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Decoding errors get thrown as 500&amp;rsquo;s before they even hit the handler. I would argue that its more likely that the client sent a badly formatted request than there being an error in the decoder code. A 500 encourages the client to send the exact same request later with no changes.&lt;/p&gt;
&lt;p&gt;Hopefully sometime later 2025 / early 2026 I&amp;rsquo;ll be able to be more helpful than just complainy pants about that.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/swift-server/swift-openapi-hummingbird/issues/26#issuecomment-3250491543&#34;&gt;https://github.com/swift-server/swift-openapi-hummingbird/issues/26#issuecomment-3250491543&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://forums.swift.org/t/openapi-trying-to-use-soar-0011-errorhandlingmiddleware/&#34;&gt;https://forums.swift.org/t/openapi-trying-to-use-soar-0011-errorhandlingmiddleware/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In the mean time, the tests look for that expectation:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;notAnID&lt;/span&gt; = &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;jieoGEJg&amp;#34;&lt;/span&gt;  &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//change to malformed&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;_&lt;/span&gt; = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; await client.execute(uri: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;&lt;span style=&#34;color:#f5a97f&#34;&gt;Self&lt;/span&gt;.APIBase&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;/&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;notAnID&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;, method: .&lt;span style=&#34;color:#c6a0f6&#34;&gt;get&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          response &lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// &lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;TODO:&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt; THIS IS BAD&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// EXAMPLE OF 500 PROBLEM!!!&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// #expect(response.status == .badRequest)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          #expect(response.status == .internalServerError)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;summary&#34;&gt;Summary&lt;/h2&gt;
&lt;p&gt;So I can see where codifying the API would be invaluable for production servers and for APIs that will have a lot of clients. Having generated code that doesn&amp;rsquo;t allow for mistakes, fantastic. The ability to share this API in a language agnostic way, also incredibly useful.&lt;/p&gt;
&lt;p&gt;On the negative side, I felt like the really long type names from the generator encourages writing hard to read code. I also missed having the ability to intercept more of errors from within the handler.&lt;/p&gt;
&lt;p&gt;There&amp;rsquo;s more to say about the generator and Hummingbird but the next few posts will be back to hardware!&lt;/p&gt;
</description>
    </item>
    
    
    
    <item>
      <title>How do I get Hummingbird to work with the OpenAPI plugins?</title>
      <link>https://whynotestflight.com/excuses/how-do-i-get-hummingbird-to-work-with-the-openapi-plugins/</link>
      <pubDate>Fri, 19 Sep 2025 00:00:00 +0000</pubDate>
      
      <guid>https://whynotestflight.com/excuses/how-do-i-get-hummingbird-to-work-with-the-openapi-plugins/</guid>
      <description>&lt;p&gt;What is OpenAPI? Originally part of &lt;a href=&#34;https://swagger.io/docs/specification/v3_0/about/&#34;&gt;swagger&lt;/a&gt; in the their own words &lt;a href=&#34;https://www.openapis.org/what-is-openapi&#34;&gt;from the docs&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The OpenAPI Specification (OAS) provides a consistent means to carry information through each stage of the API lifecycle. It is a specification language for HTTP APIs that defines structure and syntax in a way that is not wedded to the programming language the API is created in. API specifications are typically written in YAML or JSON, allowing for easy sharing and consumption of the specification.&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;That YAML file might look something like&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-yaml&#34; data-lang=&#34;yaml&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;openapi&lt;/span&gt;: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#39;3.1.0&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;info&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#c6a0f6&#34;&gt;title&lt;/span&gt;: AppService
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#c6a0f6&#34;&gt;version&lt;/span&gt;: &lt;span style=&#34;color:#f5a97f&#34;&gt;1.0.0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;servers&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  - &lt;span style=&#34;color:#c6a0f6&#34;&gt;url&lt;/span&gt;: https://example.com/api
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;description&lt;/span&gt;: App service deployment.
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;paths&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#c6a0f6&#34;&gt;/&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;get&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#c6a0f6&#34;&gt;operationId&lt;/span&gt;: getHello
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#c6a0f6&#34;&gt;responses&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;&amp;#39;200&amp;#39;&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#c6a0f6&#34;&gt;description&lt;/span&gt;: Hello!
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#c6a0f6&#34;&gt;content&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;text/plain&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;              &lt;span style=&#34;color:#c6a0f6&#34;&gt;schema&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#c6a0f6&#34;&gt;type&lt;/span&gt;: string
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;That document describes a service that offers one API endpoint &amp;ldquo;/&amp;rdquo;. It is expected to return a HTTP response with a status code of &amp;ldquo;200&amp;rdquo; and the content type of &amp;ldquo;text/plain&amp;rdquo; with the data &lt;a href=&#34;https://swagger.io/specification/#schema-object&#34;&gt;schema&lt;/a&gt; of an unnamed string.&lt;/p&gt;
&lt;p&gt;That YAML comes from the &lt;a href=&#34;https://github.com/hummingbird-project/template&#34;&gt;starter template for Hummingbird&lt;/a&gt;. Running the download script and following the prompts creates a package with all the necessary dependencies for use with Hummingbird already installed.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;curl -L https://raw.githubusercontent.com/hummingbird-project/template/main/scripts/download.sh | bash
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Some things to notice include that the YAML file I just showed lives in its own library. The premise being that that will change infrequently and as a dependency will be compiled first. This is important because the &lt;a href=&#34;https://github.com/apple/swift-openapi-generator&#34;&gt;swift-openapi-generator&lt;/a&gt; creates code it puts straight in the build folder.&lt;/p&gt;
&lt;p&gt;For example:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ls -al .build/plugins/outputs/helloopenapi/AppAPI/destination/OpenAPIGenerator/GeneratedSources
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;##yields: Client.swift	Server.swift	Types.swift&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;That glue code will make it possible to make compiler checked type constrained endpoint handlers.&lt;/p&gt;
&lt;h2 id=&#34;resources&#34;&gt;Resources&lt;/h2&gt;
&lt;p&gt;Before going any further, it will be easier to follow along after at least skimming some of the resources below:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://learn.openapis.org&#34;&gt;https://learn.openapis.org&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://swagger.io/docs/specification/v3_0/about/&#34;&gt;https://swagger.io/docs/specification/v3_0/about/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://support.smartbear.com/swaggerhub/docs/en/get-started/openapi-3-0-tutorial.html&#34;&gt;https://support.smartbear.com/swaggerhub/docs/en/get-started/openapi-3-0-tutorial.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Meet Swift OpenAPI Generator: &lt;a href=&#34;https://developer.apple.com/videos/play/wwdc2023/10171&#34;&gt;https://developer.apple.com/videos/play/wwdc2023/10171&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://www.swift.org/blog/introducing-swift-openapi-generator/&#34;&gt;https://www.swift.org/blog/introducing-swift-openapi-generator/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://swiftpackageindex.com/apple/swift-openapi-generator/1.10.3/tutorials/swift-openapi-generator&#34;&gt;https://swiftpackageindex.com/apple/swift-openapi-generator/1.10.3/tutorials/swift-openapi-generator&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://swiftonserver.com/using-openapi-with-hummingbird/&#34;&gt;https://swiftonserver.com/using-openapi-with-hummingbird/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/apple/swift-openapi-generator/tree/main/Examples/hello-world-hummingbird-server-example&#34;&gt;https://github.com/apple/swift-openapi-generator/tree/main/Examples/hello-world-hummingbird-server-example&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://forums.swift.org/tag/openapi&#34;&gt;https://forums.swift.org/tag/openapi&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/hummingbird-project/hummingbird-examples/tree/main/todos-mongokitten-openapi&#34;&gt;https://github.com/hummingbird-project/hummingbird-examples/tree/main/todos-mongokitten-openapi&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/swift-server/swift-openapi-hummingbird&#34;&gt;https://github.com/swift-server/swift-openapi-hummingbird&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;non-swift alternative: &lt;a href=&#34;https://fastapi.tiangolo.com&#34;&gt;https://fastapi.tiangolo.com&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;whats-in-the-basic-example&#34;&gt;What&amp;rsquo;s in The Basic Example&lt;/h2&gt;
&lt;p&gt;After creating the basic example I changed the name of my server app to &amp;ldquo;circusServer&amp;rdquo; and the API to the &amp;ldquo;ClownAPI&amp;rdquo;. I change names like that to try to pull apart what&amp;rsquo;s a defined term and what&amp;rsquo;s a convention in the generated code.&lt;/p&gt;
&lt;h3 id=&#34;packageswift&#34;&gt;Package.swift&lt;/h3&gt;
&lt;p&gt;I moved the tools up to 6.2 and everything still works.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// swift-tools-version:6.2&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// The swift-tools-version declares the minimum version of Swift required to build this package.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;PackageDescription&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;package&lt;/span&gt; = Package(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    name: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;circusServer&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    platforms: [.macOS(.v14), .iOS(.v17), .tvOS(.v17)],
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    products: [
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        .executable(name: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;circusServer&amp;#34;&lt;/span&gt;, targets: [&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;circusServer&amp;#34;&lt;/span&gt;]),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    ],
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    dependencies: [
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        .package(url: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;https://github.com/hummingbird-project/hummingbird.git&amp;#34;&lt;/span&gt;, from: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;2.0.0&amp;#34;&lt;/span&gt;),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        .package(url: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;https://github.com/apple/swift-argument-parser.git&amp;#34;&lt;/span&gt;, from: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;1.3.0&amp;#34;&lt;/span&gt;),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        .package(url: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;https://github.com/apple/swift-openapi-generator&amp;#34;&lt;/span&gt;, from: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;1.6.0&amp;#34;&lt;/span&gt;),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        .package(url: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;https://github.com/apple/swift-openapi-runtime&amp;#34;&lt;/span&gt;, from: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;1.7.0&amp;#34;&lt;/span&gt;),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        .package(url: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;https://github.com/swift-server/swift-openapi-hummingbird.git&amp;#34;&lt;/span&gt;, from: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;2.0.1&amp;#34;&lt;/span&gt;),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    ],
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    targets: [
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        .executableTarget(name: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;circusServer&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            dependencies: [
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                .product(name: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;ArgumentParser&amp;#34;&lt;/span&gt;, package: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;swift-argument-parser&amp;#34;&lt;/span&gt;),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                .product(name: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Hummingbird&amp;#34;&lt;/span&gt;, package: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;hummingbird&amp;#34;&lt;/span&gt;),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                .byName(name: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;ClownAPI&amp;#34;&lt;/span&gt;),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                .product(name: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;OpenAPIRuntime&amp;#34;&lt;/span&gt;, package: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;swift-openapi-runtime&amp;#34;&lt;/span&gt;),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                .product(name: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;OpenAPIHummingbird&amp;#34;&lt;/span&gt;, package: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;swift-openapi-hummingbird&amp;#34;&lt;/span&gt;),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            ],
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            path: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Sources/Circus&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        ),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        .target(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            name: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;ClownAPI&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            dependencies: [
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                .product(name: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;OpenAPIRuntime&amp;#34;&lt;/span&gt;, package: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;swift-openapi-runtime&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            ],
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            path: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Sources/ClownAPI&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            plugins: [.plugin(name: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;OpenAPIGenerator&amp;#34;&lt;/span&gt;, package: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;swift-openapi-generator&amp;#34;&lt;/span&gt;)],
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        ),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        .testTarget(name: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;AppTests&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            dependencies: [
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                .byName(name: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;circusServer&amp;#34;&lt;/span&gt;),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                .product(name: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;HummingbirdTesting&amp;#34;&lt;/span&gt;, package: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;hummingbird&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            ],
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            path: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Tests/AppTests&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        )
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    ]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;clownapi&#34;&gt;ClownAPI&lt;/h3&gt;
&lt;p&gt;The clown API folder has 3 files&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;ClownAPI.swift&lt;/strong&gt;: empty file to trigger the package to compile&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;openapi-generator-config.yaml&lt;/strong&gt;: the file that tells the generator what types of files to generate&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;openapi.yaml&lt;/strong&gt;: the file that says what rules the API should follow&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I showed the contents of openapi.yaml above, but the generator config contains&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;generate:
  - types
  - server
accessModifier: package
namingStrategy: idiomatic
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;After running a build, &lt;code&gt;cat&lt;/code&gt;&amp;lsquo;ing out the contents of the Client.swift will reveal it to be an empty file because the &lt;a href=&#34;https://swiftpackageindex.com/apple/swift-openapi-generator/1.10.3/documentation/swift-openapi-generator/configuring-the-generator&#34;&gt;config does not request a client&lt;/a&gt;.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## new folder after the name changes&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ls -al .build/plugins/outputs/helloopenapi/ClownAPI/destination/OpenAPIGenerator/GeneratedSources
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;##yields: Client.swift	Server.swift	Types.swift&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;cat .build/plugins/outputs/helloopenapi/ClownAPI/destination/OpenAPIGenerator/GeneratedSources/Client.swift
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;defining-the-handlers&#34;&gt;Defining The Handlers&lt;/h3&gt;
&lt;p&gt;Back in the server, instead of a &lt;a href=&#34;https://whynotestflight.com/excuses/how-do-i-use-hummingbird-to-make-a-basic-crud-api/#the-controller--the-tests&#34;&gt;ClownController&lt;/a&gt;, this time there&amp;rsquo;s an &lt;code&gt;APIImplementation.swift&lt;/code&gt;, which implements the &lt;code&gt;APIProtocol&lt;/code&gt; placed by the generator in &lt;code&gt;Types.swift&lt;/code&gt;. (The name &lt;code&gt;APIImplementation&lt;/code&gt; can be changed and will be &lt;a href=&#34;https://github.com/carlynorama/HummingbirdExamples/blob/main/06_openAPI/helloOpenAPI/Sources/Circus/ClownStuff/ClownAPIHandler.swift&#34;&gt;&lt;code&gt;ClownAPIHandler&lt;/code&gt;&lt;/a&gt; in the &lt;a href=&#34;https://github.com/carlynorama/HummingbirdExamples/tree/main/06_openAPI&#34;&gt;finished demo&lt;/a&gt;.)&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;ClownAPI&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;OpenAPIRuntime&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;APIImplementation&lt;/span&gt;: APIProtocol {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;getHello&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; input: ClownAPI.Operations.GetHello.Input) async &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; -&amp;gt; ClownAPI.Operations.GetHello.Output {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; .ok(.&lt;span style=&#34;color:#ed8796&#34;&gt;init&lt;/span&gt;(body: .plainText(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Hello!&amp;#34;&lt;/span&gt;)))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Excerpt from Types.swift&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;/// A type that performs HTTP operations defined by the OpenAPI document.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;package &lt;span style=&#34;color:#ed8796&#34;&gt;protocol&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;APIProtocol&lt;/span&gt;: Sendable {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;/// - Remark: HTTP `GET /`.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;/// - Remark: Generated from `#/paths///get(getHello)`.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;getHello&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; input: Operations.GetHello.Input) async &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; -&amp;gt; Operations.GetHello.Output
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;But what&amp;rsquo;s the deal with those crazy input and output types? They get generated too, for each route there will be a Operations.$ROUTE_NAME that will hold the expected input types and allowed output types outlined by the &lt;code&gt;openapi.yaml&lt;/code&gt;.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;package &lt;span style=&#34;color:#ed8796&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;id&lt;/span&gt;: Swift.&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt; = &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;getHello&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        package &lt;span style=&#34;color:#ed8796&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;Input&lt;/span&gt;: Sendable, &lt;span style=&#34;color:#91d7e3&#34;&gt;Hashable&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;/// - Remark: Generated from `#/paths/GET/header`.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            package &lt;span style=&#34;color:#ed8796&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;Headers&lt;/span&gt;: Sendable, &lt;span style=&#34;color:#91d7e3&#34;&gt;Hashable&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                package &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;accept&lt;/span&gt;: [OpenAPIRuntime.AcceptHeaderContentType&amp;lt;Operations.GetHello.AcceptableContentType&amp;gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;/// Creates a new `Headers`.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;///&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;/// - Parameters:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;///   - accept:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                package &lt;span style=&#34;color:#ed8796&#34;&gt;init&lt;/span&gt;(accept: [OpenAPIRuntime.AcceptHeaderContentType&amp;lt;Operations.GetHello.AcceptableContentType&amp;gt;] = .defaultValues()) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;.accept = accept
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            package &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;headers&lt;/span&gt;: Operations.GetHello.Input.Headers
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;/// Creates a new `Input`.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;///&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;/// - Parameters:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;///   - headers:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            package &lt;span style=&#34;color:#ed8796&#34;&gt;init&lt;/span&gt;(headers: Operations.GetHello.Input.Headers = .&lt;span style=&#34;color:#ed8796&#34;&gt;init&lt;/span&gt;()) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;.headers = headers
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        @frozen package &lt;span style=&#34;color:#ed8796&#34;&gt;enum&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;Output&lt;/span&gt;: Sendable, &lt;span style=&#34;color:#91d7e3&#34;&gt;Hashable&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            package &lt;span style=&#34;color:#ed8796&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;Ok&lt;/span&gt;: Sendable, &lt;span style=&#34;color:#91d7e3&#34;&gt;Hashable&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;/// - Remark: Generated from `#/paths/GET/responses/200/content`.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                @frozen package &lt;span style=&#34;color:#ed8796&#34;&gt;enum&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;Body&lt;/span&gt;: Sendable, &lt;span style=&#34;color:#91d7e3&#34;&gt;Hashable&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;/// - Remark: Generated from `#/paths/GET/responses/200/content/text\/plain`.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    &lt;span style=&#34;color:#c6a0f6&#34;&gt;case&lt;/span&gt; plainText(OpenAPIRuntime.HTTPBody)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;/// The associated value of the enum case if `self` is `.plainText`.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;///&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;/// - Throws: An error if `self` is not `.plainText`.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;/// - SeeAlso: `.plainText`.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    package &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;plainText&lt;/span&gt;: OpenAPIRuntime.HTTPBody {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                        &lt;span style=&#34;color:#c6a0f6&#34;&gt;get&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                            &lt;span style=&#34;color:#c6a0f6&#34;&gt;switch&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                            &lt;span style=&#34;color:#c6a0f6&#34;&gt;case&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; .plainText(body):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                                &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; body
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                            }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;/// Received HTTP response body&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                package &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;body&lt;/span&gt;: Operations.GetHello.Output.Ok.Body
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;/// Creates a new `Ok`.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;///&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;/// - Parameters:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;///   - body: Received HTTP response body&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                package &lt;span style=&#34;color:#ed8796&#34;&gt;init&lt;/span&gt;(body: Operations.GetHello.Output.Ok.Body) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;.body = body
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;/// Hello!&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;///&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;/// - Remark: Generated from `#/paths///get(getHello)/responses/200`.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;///&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;/// HTTP response code: `200 ok`.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;case&lt;/span&gt; ok(Operations.GetHello.Output.Ok)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;/// The associated value of the enum case if `self` is `.ok`.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;///&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;/// - Throws: An error if `self` is not `.ok`.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;/// - SeeAlso: `.ok`.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            package &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;ok&lt;/span&gt;: Operations.GetHello.Output.Ok {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#c6a0f6&#34;&gt;get&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    &lt;span style=&#34;color:#c6a0f6&#34;&gt;switch&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    &lt;span style=&#34;color:#c6a0f6&#34;&gt;case&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; .ok(response):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                        &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; response
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    &lt;span style=&#34;color:#c6a0f6&#34;&gt;default&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                        &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; throwUnexpectedResponseStatus(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                            expectedStatus: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;ok&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                            response: &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                        )
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;/// Undocumented response.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;///&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;/// A response with a code that is not documented in the OpenAPI document.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;case&lt;/span&gt; undocumented(statusCode: Swift.&lt;span style=&#34;color:#91d7e3&#34;&gt;Int&lt;/span&gt;, OpenAPIRuntime.UndocumentedPayload)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;These types are enums within enums, so looking at the the &lt;code&gt;getHello&lt;/code&gt; example above, we have the &lt;code&gt;Output&lt;/code&gt; enum with the case &lt;code&gt;ok&lt;/code&gt; taking in a &lt;code&gt;Body&lt;/code&gt; enum with its single allowable case of &lt;code&gt;.plainText&lt;/code&gt; that has an associated type of &lt;a href=&#34;https://github.com/apple/swift-openapi-runtime/blob/7722cf8eac05c1f1b5b05895b04cfcc29576d9be/Sources/OpenAPIRuntime/Interface/HTTPBody.swift#L119&#34;&gt;&lt;code&gt;OpenAPIRuntime.HTTPBody&lt;/code&gt;&lt;/a&gt;. &lt;code&gt;OpenAPIRuntime.HTTPBody&lt;/code&gt; has &lt;a href=&#34;https://github.com/apple/swift-openapi-runtime/blob/7722cf8eac05c1f1b5b05895b04cfcc29576d9be/Sources/OpenAPIRuntime/Interface/HTTPBody.swift#L232&#34;&gt;several convenience initializers&lt;/a&gt;, but none of them actually take a &lt;code&gt;String&lt;/code&gt;. What we&amp;rsquo;re seeing in the example is a &lt;code&gt;StaticString&lt;/code&gt;, which behaves differently. A string can be used, it just needs to be transformed into its &lt;code&gt;UInt8&lt;/code&gt; bytes first.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// Works&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;getHello&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; input: ClownAPI.Operations.GetHello.Input) async &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; -&amp;gt; ClownAPI.Operations.GetHello.Output {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; .ok(.&lt;span style=&#34;color:#ed8796&#34;&gt;init&lt;/span&gt;(body: .plainText(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Hello!&amp;#34;&lt;/span&gt;)))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// Does not work. &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;getHello&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; input: Operations.GetHello.Input) async &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; -&amp;gt; Operations.GetHello.Output {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// 1.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;message&lt;/span&gt; = &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Hello!&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//Cannot convert value of type &amp;#39;String&amp;#39; to expected argument type &amp;#39;HTTPBody&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; .ok(.&lt;span style=&#34;color:#ed8796&#34;&gt;init&lt;/span&gt;(body: .plainText(message)))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// Does work&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;getHello&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; input: Operations.GetHello.Input) async &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; -&amp;gt; Operations.GetHello.Output {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;message&lt;/span&gt; = &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Hello&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; .ok(.&lt;span style=&#34;color:#ed8796&#34;&gt;init&lt;/span&gt;(body: .plainText(.&lt;span style=&#34;color:#ed8796&#34;&gt;init&lt;/span&gt;(message.utf8))))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;That can be hard to follow with all those &lt;code&gt;.inits&lt;/code&gt;. Here is that last call written out the super long way:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;getHello&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; input: Operations.GetHello.Input) async &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; -&amp;gt; Operations.GetHello.Output {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//return .ok(.init(body: .plainText(&amp;#34;Hello!&amp;#34;)))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;message&lt;/span&gt; = &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Hello&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;bytes&lt;/span&gt;:[&lt;span style=&#34;color:#91d7e3&#34;&gt;UInt8&lt;/span&gt;] = &lt;span style=&#34;color:#91d7e3&#34;&gt;Array&lt;/span&gt;(message.utf8) 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;httpBody&lt;/span&gt; = OpenAPIRuntime.HTTPBody(bytes)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;okBody&lt;/span&gt; = Operations.GetHello.Output.Ok.Body.plainText(httpBody)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;greetOk&lt;/span&gt; = Operations.GetHello.Output.Ok(body: okBody)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;greetOutput&lt;/span&gt; = Operations.GetHello.Output.ok(greetOk)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; greetOutput
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;adding-the-routes&#34;&gt;Adding the Routes&lt;/h3&gt;
&lt;p&gt;To get those functions registered with the Hummingbird router, 3 things have to happen in &lt;code&gt;Application+build.swift&lt;/code&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The &lt;code&gt;OpenAPIHummingbird&lt;/code&gt; glue library needs to be imported&lt;/li&gt;
&lt;li&gt;Optionally the &lt;code&gt;OpenAPIRequestContextMiddleware()&lt;/code&gt; generated by the template has to be added to the Middleware Group. It&amp;rsquo;s needed if a  Hummingbird context will be used in an OpenAPIRuntime endpoint handler. It does this by storing the Context in &lt;a href=&#34;https://github.com/swift-server/swift-openapi-hummingbird/blob/c464db1afe2c886083fd60e38f281150ac7e73e5/README.md?plain=1#L24&#34;&gt;TaskLocal&lt;/a&gt; (&lt;a href=&#34;https://developer.apple.com/documentation/swift/tasklocal&#34;&gt;more&lt;/a&gt;, &lt;a href=&#34;https://www.hackingwithswift.com/quick-start/concurrency/how-to-create-and-use-task-local-values&#34;&gt;reading&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;The Routes need to be added! The new packages (generator, runtime, hummingbird-openapi) do some fancy magic under the hood with conjuring up the proper &lt;code&gt;registerHandlers&lt;/code&gt; function for the desired server underpinning. Yet another possible post / set of posts&amp;hellip;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/apple/swift-openapi-generator/blob/main/Sources/_OpenAPIGeneratorCore/Translator/ServerTranslator/ServerTranslator.swift#L75&#34;&gt;https://github.com/apple/swift-openapi-generator/blob/main/Sources/_OpenAPIGeneratorCore/Translator/ServerTranslator/ServerTranslator.swift#L75&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//# 1 Add the Glue&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;OpenAPIHummingbird&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;/// Build router&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;buildRouter&lt;/span&gt;() &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; -&amp;gt; Router&amp;lt;AppRequestContext&amp;gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;router&lt;/span&gt; = Router(context: AppRequestContext.&lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// Add middleware&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    router.addMiddleware {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// logging middleware&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        LogRequestsMiddleware(.info)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//# 2: store request context in TaskLocal&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        OpenAPIRequestContextMiddleware()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// # 3 Add OpenAPI handlers&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;api&lt;/span&gt; = APIImplementation()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; api.registerHandlers(on: router)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; router
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;summary&#34;&gt;Summary&lt;/h2&gt;
&lt;p&gt;That&amp;rsquo;s all the pieces in the starter OpenAPI Hummingbird template combo before starting to add in all the CRUD implementation details.&lt;/p&gt;
</description>
    </item>
    
    
    
    <item>
      <title>How do I use Hummingbird to make a basic CRUD API?</title>
      <link>https://whynotestflight.com/excuses/how-do-i-use-hummingbird-to-make-a-basic-crud-api/</link>
      <pubDate>Thu, 18 Sep 2025 00:00:00 +0000</pubDate>
      
      <guid>https://whynotestflight.com/excuses/how-do-i-use-hummingbird-to-make-a-basic-crud-api/</guid>
      <description>&lt;p&gt;So my recommendation is to also go through &lt;a href=&#34;https://docs.hummingbird.codes/2.0/tutorials/todos&#34;&gt;Hummingbird TODO&amp;rsquo;s example&lt;/a&gt;, because that&amp;rsquo;s what I did to learn how to write this code. The main difference between that tutorial&amp;rsquo;s early steps and what I&amp;rsquo;ve done here is that I&amp;rsquo;ve uses &lt;a href=&#34;https://github.com/swiftlang/swift-testing&#34;&gt;swift-testing&lt;/a&gt; and that example still uses XCTests (at date published).&lt;/p&gt;
&lt;p&gt;That tutorial goes on to add persistence through a postgres database, which I haven&amp;rsquo;t here. I&amp;rsquo;ll mention some options beside postgres in the &lt;a href=&#34;#the-repository&#34;&gt;Repository section&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Hummingbird makes it &lt;a href=&#34;https://github.com/carlynorama/HummingbirdExamples/blob/78bea4fac99764653283b12c40f075f47152403b/02_basic_responses/simple-respond/Sources/simple-respond/Application%2Bbuild.swift#L149&#34;&gt;&lt;em&gt;incredibly&lt;/em&gt; easy&lt;/a&gt; to return JSON for &lt;code&gt;Encodable&lt;/code&gt;s.&lt;/p&gt;
&lt;p&gt;But to do the standard &lt;a href=&#34;https://en.wikipedia.org/wiki/Create,_read,_update_and_delete&#34;&gt;crud functions&lt;/a&gt; on a collection of that type, there are some things to do!&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Have a type&lt;/li&gt;
&lt;li&gt;Make a store/repository to manage the collection of that type.&lt;/li&gt;
&lt;li&gt;Make a RouteCollection, or really &amp;ldquo;Controller&amp;rdquo; that can offer one up.&lt;/li&gt;
&lt;li&gt;WRITE TESTS&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This code is available as a swift Package at:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/carlynorama/HummingbirdExamples/tree/main/05_helloCRUD&#34;&gt;https://github.com/carlynorama/HummingbirdExamples/tree/main/05_helloCRUD&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;the-type&#34;&gt;The Type&lt;/h2&gt;
&lt;p&gt;My type is a Clown, and it conforms to quite a few things.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;Clown&lt;/span&gt;: Decodable, ResponseEncodable, Sendable, &lt;span style=&#34;color:#91d7e3&#34;&gt;Equatable&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;id&lt;/span&gt;: &lt;span style=&#34;color:#91d7e3&#34;&gt;Int&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;name&lt;/span&gt;: &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;spareNoses&lt;/span&gt;: &lt;span style=&#34;color:#91d7e3&#34;&gt;Int&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Decodable:&lt;/strong&gt; So the default Hummingbird context make one from JSON that comes in&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;ResponseEncodable:&lt;/strong&gt; So the default Hummingbird context can make the JSON and wrap it in a response&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Sendable:&lt;/strong&gt; so the sendable endpoint handlers can work with them and send them both out via JSON and to the actor based repository.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Equatable:&lt;/strong&gt; I believe I added this for testing&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Not Yet:&lt;/strong&gt; Comparable. But go ahead and add it for sorting list views more conveniently if desired.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;the-repository&#34;&gt;The Repository&lt;/h2&gt;
&lt;p&gt;In Hummingbird examples the &lt;a href=&#34;https://en.wikipedia.org/wiki/Data_store&#34;&gt;data store&lt;/a&gt; is generally referred to as a repository (although I called my repository &lt;code&gt;ClownCar&lt;/code&gt;).&lt;/p&gt;
&lt;p&gt;This type manages the collection of Clowns I&amp;rsquo;ll be editing. The API controller never touches the underlying storage itself, everything goes through a repository&amp;rsquo;s interface.&lt;/p&gt;
&lt;p&gt;Right now my store is all in memory. Hopefully a future article will cover persistence between server runs, but I&amp;rsquo;ll list some of the options:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;the &lt;a href=&#34;(https://docs.hummingbird.codes/2.0/tutorials/todos)&#34;&gt;TODO&amp;rsquo;s example&lt;/a&gt; shows one method using postgres,&lt;/li&gt;
&lt;li&gt;the examples folder contain &lt;a href=&#34;https://github.com/hummingbird-project/hummingbird-examples/tree/main/todos-fluent&#34;&gt;examples&lt;/a&gt; for &lt;a href=&#34;https://github.com/hummingbird-project/hummingbird-examples/tree/main/todos-mongokitten-openapi&#34;&gt;other&lt;/a&gt; methods,&lt;/li&gt;
&lt;li&gt;and the docs talk about the &lt;a href=&#34;https://docs.hummingbird.codes/2.0/documentation/hummingbird/persistentdata&#34;&gt;persistence driver&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;actor ClownCar {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;clowns&lt;/span&gt;: [&lt;span style=&#34;color:#91d7e3&#34;&gt;Int&lt;/span&gt;: Clown]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#ed8796&#34;&gt;init&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    clowns = [
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f5a97f&#34;&gt;0&lt;/span&gt;: Clown(id: &lt;span style=&#34;color:#f5a97f&#34;&gt;0&lt;/span&gt;, name: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Pagliacci&amp;#34;&lt;/span&gt;, spareNoses: &lt;span style=&#34;color:#f5a97f&#34;&gt;0&lt;/span&gt;),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f5a97f&#34;&gt;1&lt;/span&gt;: Clown(id: &lt;span style=&#34;color:#f5a97f&#34;&gt;1&lt;/span&gt;, name: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Joseph Grimaldi&amp;#34;&lt;/span&gt;, spareNoses: &lt;span style=&#34;color:#f5a97f&#34;&gt;41417&lt;/span&gt;),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f5a97f&#34;&gt;4&lt;/span&gt;: Clown(id: &lt;span style=&#34;color:#f5a97f&#34;&gt;4&lt;/span&gt;, name: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Weary Willie&amp;#34;&lt;/span&gt;, spareNoses: &lt;span style=&#34;color:#f5a97f&#34;&gt;1&lt;/span&gt;),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//Clown(id: 224111, name:&amp;#34;Bozo&amp;#34; , spareNoses: 4141),&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    ]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// CREATE&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;/// create a clown.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;create&lt;/span&gt;(name: &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;, spareNoses: &lt;span style=&#34;color:#91d7e3&#34;&gt;Int&lt;/span&gt; = &lt;span style=&#34;color:#f5a97f&#34;&gt;10&lt;/span&gt;) async &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; -&amp;gt; Clown {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;id&lt;/span&gt; = &lt;span style=&#34;color:#91d7e3&#34;&gt;Int&lt;/span&gt;.random(&lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt;: &lt;span style=&#34;color:#f5a97f&#34;&gt;1000.&lt;/span&gt;.&amp;lt;&lt;span style=&#34;color:#f5a97f&#34;&gt;10000&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;clown&lt;/span&gt; = Clown(id: id, name: name, spareNoses: spareNoses)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;.clowns[id] = clown
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; clown
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// READ&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;/// Get clown&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;get&lt;/span&gt;(id: &lt;span style=&#34;color:#91d7e3&#34;&gt;Int&lt;/span&gt;) async &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; -&amp;gt; Clown? {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;.clowns[id]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;/// List all clowns&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;list&lt;/span&gt;() async &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; -&amp;gt; [Clown] {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;.clowns.values.&lt;span style=&#34;color:#91d7e3&#34;&gt;map&lt;/span&gt; { &lt;span style=&#34;color:#f4dbd6&#34;&gt;$0&lt;/span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//UPDATE&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;/// Update clown. Returns updated clown if successful&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// note all the optional fields...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;update&lt;/span&gt;(id: &lt;span style=&#34;color:#91d7e3&#34;&gt;Int&lt;/span&gt;, name: &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;?, spareNoses: &lt;span style=&#34;color:#91d7e3&#34;&gt;Int&lt;/span&gt;?) async &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; -&amp;gt; Clown? {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;clown&lt;/span&gt; = &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;.clowns[id] {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;name&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        clown.name = name
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;spareNoses&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        clown.spareNoses = spareNoses
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;.clowns[id] = clown
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; clown
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;nil&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//DELETE&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;/// Delete clown. Returns true if successful&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;delete&lt;/span&gt;(id: &lt;span style=&#34;color:#91d7e3&#34;&gt;Int&lt;/span&gt;) async &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; -&amp;gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;Bool&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;.clowns[id] &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;!=&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;nil&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;.clowns[id] = &lt;span style=&#34;color:#f5a97f&#34;&gt;nil&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;false&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;/// Delete all clowns&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;deleteAll&lt;/span&gt;() async &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;.clowns = [:]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;the-controller--the-tests&#34;&gt;The Controller &amp;amp; The Tests&lt;/h2&gt;
&lt;p&gt;This CRUD needs to be linked up to the API, so lets make a &lt;a href=&#34;https://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93controller&#34;&gt;Controller&lt;/a&gt; type to glue the model to the data output &amp;ldquo;views.&amp;rdquo;&lt;/p&gt;
&lt;p&gt;This Controller has three main jobs,&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;To hold a repository instance to store the data (a &lt;code&gt;ClownCar&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;To provide a variable that can serve up a &lt;a href=&#34;https://github.com/hummingbird-project/hummingbird/blob/main&#34;&gt;RouteCollection&lt;/a&gt; (more &lt;a href=&#34;https://docs.hummingbird.codes/2.0/documentation/hummingbird/routecollection&#34;&gt;docs&lt;/a&gt;), specified to the appropriate context. (Also read about &lt;a href=&#34;https://docs.hummingbird.codes/2.0/documentation/hummingbird/routergroup&#34;&gt;RouterGroup&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;To house the api endpoint handlers listed in the RouteCollection (&lt;code&gt;(request, context) -&amp;gt; ResponseGenerator&lt;/code&gt; types)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;NOTE: With so many types being generic with respect to the Apps base context type its easier to change an apps context by providing a &lt;a href=&#34;https://github.com/carlynorama/HummingbirdExamples/blob/6e5a25c1ad3957dc8f9482a68623c68cfb232434/05_crud/helloCRUD/Sources/helloCRUD/Application%2Bbuild.swift#L15&#34;&gt;type alias&lt;/a&gt;.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;Hummingbird&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#if&lt;/span&gt; &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;canImport&lt;/span&gt;(&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;FoundationEssentials&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#ed8796&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;FoundationEssentials&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#else&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#ed8796&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;Foundation&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#endif&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;ClownController&lt;/span&gt;: Sendable {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// clown repository&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;repository&lt;/span&gt;: ClownCar
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// return clown endpoints&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;endpoints&lt;/span&gt;: RouteCollection&amp;lt;AppRequestContext&amp;gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;routes&lt;/span&gt; = RouteCollection(context: AppRequestContext.&lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//routes.group(context: FlexContext.self)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    routes.group()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      .&lt;span style=&#34;color:#c6a0f6&#34;&gt;get&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;:id&amp;#34;&lt;/span&gt;, use: &lt;span style=&#34;color:#c6a0f6&#34;&gt;get&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      .&lt;span style=&#34;color:#c6a0f6&#34;&gt;get&lt;/span&gt;(use: list)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      .post(use: create)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      .patch(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;:id&amp;#34;&lt;/span&gt;, use: update)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      .patch(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;{id}/honk&amp;#34;&lt;/span&gt;, use: noseDecrement)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      .delete(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;:id&amp;#34;&lt;/span&gt;, use: delete)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      .delete(use: deleteAll)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; routes
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//implementations here...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Some of the handler functions have helper structs modeling the data that a client would be actually expected to include with the request, which may not be the same as the actual base type (&lt;code&gt;Clown&lt;/code&gt;) the repository stores.&lt;/p&gt;
&lt;p&gt;Each one of these can be &lt;a href=&#34;https://github.com/carlynorama/HummingbirdExamples/blob/main/02_basic_responses/simple-respond/tests.sh&#34;&gt;tested with curl&lt;/a&gt;, but it&amp;rsquo;s easier in the long run to write the test with it at the same time, so I&amp;rsquo;ve paired those together below.&lt;/p&gt;
&lt;p&gt;Do run through &lt;a href=&#34;https://docs.hummingbird.codes/2.0/tutorials/hummingbird/todos-3-testing/&#34;&gt;the tutorial&amp;rsquo;s testing section&lt;/a&gt;, but one can use my file as a base to switch to &lt;code&gt;swift-testing&lt;/code&gt;.  That tutorial is what suggest writing helper static functions at the top which is indeed very helpful.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/carlynorama/HummingbirdExamples/blob/main/05_crud/helloCRUD/Tests/AppTests/ClownAPITests.swift&#34;&gt;https://github.com/carlynorama/HummingbirdExamples/blob/main/05_crud/helloCRUD/Tests/AppTests/ClownAPITests.swift&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I&amp;rsquo;ve wrapped the clown API tests in their own Suite, but the tests could be broken up further by tag (create, read, update, delete?) or other traits.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://developer.apple.com/documentation/testing/addingtags&#34;&gt;https://developer.apple.com/documentation/testing/addingtags&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;more about testing traits: &lt;a href=&#34;https://developer.apple.com/videos/play/wwdc2024/10179?time=360&#34;&gt;https://developer.apple.com/videos/play/wwdc2024/10179?time=360&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;extension&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;AppTests&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  @Suite(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Tests to test the Clown&amp;#39;s JSON API&amp;#34;&lt;/span&gt;) &lt;span style=&#34;color:#ed8796&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;ClownAPITests&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//your tests here&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Also note in several places the tests look for &lt;code&gt;.noContent&lt;/code&gt; instead of &lt;code&gt;.notFound&lt;/code&gt;, this is because if a &lt;code&gt;Clown?&lt;/code&gt; returns nil, Hummingbird&amp;rsquo;s default response is to return &lt;code&gt;.noContent&lt;/code&gt;. No content is &lt;a href=&#34;https://apihandyman.io/move-along-no-resource-to-see-here-seriously-http-status-code-204-vs-403-vs-404-vs-410/&#34;&gt;typically a success&lt;/a&gt; &lt;a href=&#34;https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Status/204&#34;&gt;with no body&lt;/a&gt;, which it&amp;rsquo;s entirely possible for that nil to mean in some contexts.  However, in my case that is the wrong response and if I stick with the Hummingbird handlers I will have to do something other than return a raw &lt;code&gt;Clown?&lt;/code&gt;. Perfect future use of a &lt;a href=&#34;https://www.hackingwithswift.com/articles/161/how-to-use-result-in-swift&#34;&gt;&lt;code&gt;Result&lt;/code&gt;&lt;/a&gt;? TBD.&lt;/p&gt;
&lt;h3 id=&#34;create&#34;&gt;Create&lt;/h3&gt;
&lt;h4 id=&#34;controller&#34;&gt;Controller&lt;/h4&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#ed8796&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;CreateRequest&lt;/span&gt;: Decodable {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;name&lt;/span&gt;: &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;spareNoses&lt;/span&gt;: &lt;span style=&#34;color:#91d7e3&#34;&gt;Int&lt;/span&gt;?
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;/// Create clown endpoint&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  @Sendable &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;create&lt;/span&gt;(request: Request, context: some RequestContext) async &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    -&amp;gt; EditedResponse&amp;lt;Clown&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;request&lt;/span&gt; = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; await request.decode(&lt;span style=&#34;color:#c6a0f6&#34;&gt;as&lt;/span&gt;: CreateRequest.&lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;, context: context)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;clown&lt;/span&gt; = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; await &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;.repository.create(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      name: request.name, spareNoses: request.spareNoses ?? &lt;span style=&#34;color:#f5a97f&#34;&gt;10&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; EditedResponse(status: .created, response: clown)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h4 id=&#34;tests&#34;&gt;Tests&lt;/h4&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;CreateRequest&lt;/span&gt;: Encodable {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;name&lt;/span&gt;: &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;spareNoses&lt;/span&gt;: &lt;span style=&#34;color:#91d7e3&#34;&gt;Int&lt;/span&gt;?
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;create&lt;/span&gt;(name: &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;, spareNoses: &lt;span style=&#34;color:#91d7e3&#34;&gt;Int&lt;/span&gt;? = &lt;span style=&#34;color:#f5a97f&#34;&gt;nil&lt;/span&gt;, client: some TestClientProtocol)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      async &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; -&amp;gt; Clown
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;request&lt;/span&gt; = CreateRequest(name: name, spareNoses: spareNoses)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;buffer&lt;/span&gt; = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; JSONEncoder().encodeAsByteBuffer(request, allocator: ByteBufferAllocator())
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; await client.execute(uri: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;/clowns&amp;#34;&lt;/span&gt;, method: .post, body: buffer) { response &lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        #expect(response.status == .created)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; JSONDecoder().decode(Clown.&lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;, from: response.body)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;get&lt;/span&gt;(id: &lt;span style=&#34;color:#91d7e3&#34;&gt;Int&lt;/span&gt;, client: some TestClientProtocol) async &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; -&amp;gt; Clown? {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; await client.execute(uri: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;/clowns/&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;id&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;, method: .&lt;span style=&#34;color:#c6a0f6&#34;&gt;get&lt;/span&gt;) { response &lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// either the get request returned an 200 status or it didn&amp;#39;t return a Clown&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        #expect(response.status == .ok &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;||&lt;/span&gt; response.body.readableBytes == &lt;span style=&#34;color:#f5a97f&#34;&gt;0&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; response.body.readableBytes &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;0&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; JSONDecoder().decode(Clown.&lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;, from: response.body)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        } &lt;span style=&#34;color:#c6a0f6&#34;&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;nil&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    @Test &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;testCreate&lt;/span&gt;() async &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;app&lt;/span&gt; = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; await buildApplication(TestArguments())
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; await app.test(.router) { client &lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;clownName&lt;/span&gt; = &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Bozo&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;noseCount&lt;/span&gt; = &lt;span style=&#34;color:#f5a97f&#34;&gt;17&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;clown&lt;/span&gt; = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; await &lt;span style=&#34;color:#f5a97f&#34;&gt;Self&lt;/span&gt;.create(name: clownName, spareNoses: noseCount, client: client)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        #expect(clown.name == clownName)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        #expect(clown.spareNoses == noseCount)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;retrievedClown&lt;/span&gt; = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; await &lt;span style=&#34;color:#f5a97f&#34;&gt;Self&lt;/span&gt;.&lt;span style=&#34;color:#c6a0f6&#34;&gt;get&lt;/span&gt;(id: clown.id, client: client)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        #expect(clown == retrievedClown)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;read&#34;&gt;Read&lt;/h3&gt;
&lt;h4 id=&#34;controller-1&#34;&gt;Controller&lt;/h4&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;/// Get clown endpoint&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  @Sendable &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;get&lt;/span&gt;(request: Request, context: some RequestContext) async &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; -&amp;gt; Clown? {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;id&lt;/span&gt; = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; context.parameters.require(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;id&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#c6a0f6&#34;&gt;as&lt;/span&gt;: &lt;span style=&#34;color:#91d7e3&#34;&gt;Int&lt;/span&gt;.&lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; await &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;.repository.&lt;span style=&#34;color:#c6a0f6&#34;&gt;get&lt;/span&gt;(id: id)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;/// Get list of clowns endpoint&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  @Sendable &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;list&lt;/span&gt;(request: Request, context: some RequestContext) async &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; -&amp;gt; [Clown] {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; await &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;.repository.list()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h4 id=&#34;tests-1&#34;&gt;Tests&lt;/h4&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// used in Create, too&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;get&lt;/span&gt;(id: &lt;span style=&#34;color:#91d7e3&#34;&gt;Int&lt;/span&gt;, client: some TestClientProtocol) async &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; -&amp;gt; Clown? {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;list&lt;/span&gt;(client: some TestClientProtocol) async &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; -&amp;gt; [Clown] {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; await client.execute(uri: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;/clowns&amp;#34;&lt;/span&gt;, method: .&lt;span style=&#34;color:#c6a0f6&#34;&gt;get&lt;/span&gt;) { response &lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        #expect(response.status == .ok)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; JSONDecoder().decode([Clown].&lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;, from: response.body)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    @Test &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;testClownFetch&lt;/span&gt;() async &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;app&lt;/span&gt; = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; await buildApplication(TestArguments())
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; await app.test(.router) { client &lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;goodID&lt;/span&gt; = &lt;span style=&#34;color:#f5a97f&#34;&gt;1&lt;/span&gt;  &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//start with known good.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;_&lt;/span&gt; = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; await client.execute(uri: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;/clowns/&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;goodID&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;, method: .&lt;span style=&#34;color:#c6a0f6&#34;&gt;get&lt;/span&gt;) { response &lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          #expect(response.status == .ok)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          #expect(response.headers.&lt;span style=&#34;color:#91d7e3&#34;&gt;contains&lt;/span&gt;(.contentType))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;contentType&lt;/span&gt; = response.headers[.contentType]&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;!&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          #expect(contentType == &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;application/json; charset=utf-8&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;clown&lt;/span&gt; = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; JSONDecoder().decode(Clown.&lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;, from: response.body)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//print(clown)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//In &amp;#34;real&amp;#34; app would pull this directly from the db using same ID.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;compareTo&lt;/span&gt; = Clown(id: &lt;span style=&#34;color:#f5a97f&#34;&gt;1&lt;/span&gt;, name: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Joseph Grimaldi&amp;#34;&lt;/span&gt;, spareNoses: &lt;span style=&#34;color:#f5a97f&#34;&gt;12&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          #expect(clown.name == compareTo.name)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;badID&lt;/span&gt; = &lt;span style=&#34;color:#f5a97f&#34;&gt;53_253_622&lt;/span&gt;  &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//change to known unused value&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;_&lt;/span&gt; = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; await client.execute(uri: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;/clowns/&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;badID&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;, method: .&lt;span style=&#34;color:#c6a0f6&#34;&gt;get&lt;/span&gt;) { response &lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//bad interpretation of a nil&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          #expect(response.status == .noContent)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;notAnID&lt;/span&gt; = &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;jieoGEJg&amp;#34;&lt;/span&gt;  &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//change to malformed&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;_&lt;/span&gt; = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; await client.execute(uri: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;/clowns/&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;notAnID&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;, method: .&lt;span style=&#34;color:#c6a0f6&#34;&gt;get&lt;/span&gt;) { response &lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          #expect(response.status == .badRequest)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    @Test &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;testClownsFetch&lt;/span&gt;() async &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;app&lt;/span&gt; = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; await buildApplication(TestArguments())
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; await app.test(.router) { client &lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//this is weak. If the test data, not currently managed by the test suite,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//changes, these test could fail based on that.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;goodClown&lt;/span&gt; = Clown(id: &lt;span style=&#34;color:#f5a97f&#34;&gt;1&lt;/span&gt;, name: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Joseph Grimaldi&amp;#34;&lt;/span&gt;, spareNoses: &lt;span style=&#34;color:#f5a97f&#34;&gt;41417&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;badClown&lt;/span&gt; = Clown(id: &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;-&lt;/span&gt;&lt;span style=&#34;color:#f5a97f&#34;&gt;1&lt;/span&gt;, name: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Pennywise&amp;#34;&lt;/span&gt;, spareNoses: &lt;span style=&#34;color:#f5a97f&#34;&gt;86_428_916_419&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;_&lt;/span&gt; = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; await client.execute(uri: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;/clowns/&amp;#34;&lt;/span&gt;, method: .&lt;span style=&#34;color:#c6a0f6&#34;&gt;get&lt;/span&gt;) { response &lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          #expect(response.status == .ok)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          #expect(response.headers.&lt;span style=&#34;color:#91d7e3&#34;&gt;contains&lt;/span&gt;(.contentType))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;contentType&lt;/span&gt; = response.headers[.contentType]&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;!&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          #expect(contentType == &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;application/json; charset=utf-8&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;clowns&lt;/span&gt; = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; JSONDecoder().decode([Clown].&lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;, from: response.body)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          #expect(clowns.&lt;span style=&#34;color:#91d7e3&#34;&gt;contains&lt;/span&gt;(&lt;span style=&#34;color:#c6a0f6&#34;&gt;where&lt;/span&gt;: { &lt;span style=&#34;color:#f4dbd6&#34;&gt;$0&lt;/span&gt; == goodClown }))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          #expect(&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;!&lt;/span&gt;clowns.&lt;span style=&#34;color:#91d7e3&#34;&gt;contains&lt;/span&gt;(&lt;span style=&#34;color:#c6a0f6&#34;&gt;where&lt;/span&gt;: { &lt;span style=&#34;color:#f4dbd6&#34;&gt;$0&lt;/span&gt; == badClown }))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;update&#34;&gt;Update&lt;/h3&gt;
&lt;p&gt;This update example highlights that the closure can pull data out of multiple places, the URL and the various fields of the Request.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;id&lt;/span&gt; = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; context.parameters.require(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;id&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#c6a0f6&#34;&gt;as&lt;/span&gt;: &lt;span style=&#34;color:#91d7e3&#34;&gt;Int&lt;/span&gt;.&lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;pulls the id number out of the URL.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;requestValue&lt;/span&gt; = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; await request.decode(&lt;span style=&#34;color:#c6a0f6&#34;&gt;as&lt;/span&gt;: UpdateRequest.&lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;, context: context)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Uses the &lt;a href=&#34;https://github.com/hummingbird-project/hummingbird/blob/b4f73eb35df8ecca664924b54b02b882b596cb19/Sources/Hummingbird/Server/Request.swift#L41&#34;&gt;request&amp;rsquo;s decode function&lt;/a&gt; in conjunction with &lt;a href=&#34;https://github.com/hummingbird-project/hummingbird/blob/b4f73eb35df8ecca664924b54b02b882b596cb19/Sources/Hummingbird/Server/RequestContext.swift#L114&#34;&gt;decoder from the context&lt;/a&gt; to try to get the JSON data in the request body to match the specified &lt;code&gt;UpdateRequest&lt;/code&gt;&lt;/p&gt;
&lt;h4 id=&#34;controller-2&#34;&gt;Controller&lt;/h4&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#ed8796&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;UpdateRequest&lt;/span&gt;: Decodable {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;name&lt;/span&gt;: &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;?
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;spareNoses&lt;/span&gt;: &lt;span style=&#34;color:#91d7e3&#34;&gt;Int&lt;/span&gt;?
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;/// Update clown endpoint&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  @Sendable &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;update&lt;/span&gt;(request: Request, context: some RequestContext) async &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; -&amp;gt; Clown? {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;id&lt;/span&gt; = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; context.parameters.require(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;id&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#c6a0f6&#34;&gt;as&lt;/span&gt;: &lt;span style=&#34;color:#91d7e3&#34;&gt;Int&lt;/span&gt;.&lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;requestValue&lt;/span&gt; = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; await request.decode(&lt;span style=&#34;color:#c6a0f6&#34;&gt;as&lt;/span&gt;: UpdateRequest.&lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;, context: context)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;guard&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;clown&lt;/span&gt; = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; await &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;.repository.update(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        id: id,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        name: requestValue.name,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        spareNoses: requestValue.spareNoses
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      )
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#c6a0f6&#34;&gt;throw&lt;/span&gt; HTTPError(.badRequest)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; clown
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//custom update function&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  @Sendable &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;noseDecrement&lt;/span&gt;(request: Request, context: some RequestContext) async &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    -&amp;gt; Clown?
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;honkRequestID&lt;/span&gt; = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; context.parameters.require(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;id&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#c6a0f6&#34;&gt;as&lt;/span&gt;: &lt;span style=&#34;color:#91d7e3&#34;&gt;Int&lt;/span&gt;.&lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;beforeClown&lt;/span&gt; = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; await &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;.repository.&lt;span style=&#34;color:#c6a0f6&#34;&gt;get&lt;/span&gt;(id: honkRequestID) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; await &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;.repository.update(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        id: honkRequestID, name: &lt;span style=&#34;color:#f5a97f&#34;&gt;nil&lt;/span&gt;, spareNoses: beforeClown.spareNoses &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;-&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;1&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;nil&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h4 id=&#34;tests-2&#34;&gt;Tests&lt;/h4&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//also uses the Self.get &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;UpdateRequest&lt;/span&gt;: Encodable {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;name&lt;/span&gt;: &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;?
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;spareNoses&lt;/span&gt;: &lt;span style=&#34;color:#91d7e3&#34;&gt;Int&lt;/span&gt;?
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;completed&lt;/span&gt;: &lt;span style=&#34;color:#91d7e3&#34;&gt;Bool&lt;/span&gt;?
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;patch&lt;/span&gt;(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      id: &lt;span style=&#34;color:#91d7e3&#34;&gt;Int&lt;/span&gt;, name: &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;? = &lt;span style=&#34;color:#f5a97f&#34;&gt;nil&lt;/span&gt;, spareNoses: &lt;span style=&#34;color:#91d7e3&#34;&gt;Int&lt;/span&gt;? = &lt;span style=&#34;color:#f5a97f&#34;&gt;nil&lt;/span&gt;, completed: &lt;span style=&#34;color:#91d7e3&#34;&gt;Bool&lt;/span&gt;? = &lt;span style=&#34;color:#f5a97f&#34;&gt;nil&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      client: some TestClientProtocol
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    ) async &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; -&amp;gt; Clown? {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;request&lt;/span&gt; = UpdateRequest(name: name, spareNoses: spareNoses, completed: completed)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;buffer&lt;/span&gt; = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; JSONEncoder().encodeAsByteBuffer(request, allocator: ByteBufferAllocator())
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; await client.execute(uri: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;/clowns/&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;id&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;, method: .patch, body: buffer) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        response &lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        #expect(response.status == .ok, &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;response.status&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; response.body.readableBytes &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;0&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; JSONDecoder().decode(Clown.&lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;, from: response.body)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        } &lt;span style=&#34;color:#c6a0f6&#34;&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;nil&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//    //for testing uuid is just a string so can pass garbage later.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;patchResponseStatus&lt;/span&gt;(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      id: &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;, name: &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;? = &lt;span style=&#34;color:#f5a97f&#34;&gt;nil&lt;/span&gt;, spareNoses: &lt;span style=&#34;color:#91d7e3&#34;&gt;Int&lt;/span&gt;? = &lt;span style=&#34;color:#f5a97f&#34;&gt;nil&lt;/span&gt;, completed: &lt;span style=&#34;color:#91d7e3&#34;&gt;Bool&lt;/span&gt;? = &lt;span style=&#34;color:#f5a97f&#34;&gt;nil&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      client: some TestClientProtocol
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    ) async &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; -&amp;gt; HTTPResponse.Status {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;request&lt;/span&gt; = UpdateRequest(name: name, spareNoses: spareNoses, completed: completed)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;buffer&lt;/span&gt; = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; JSONEncoder().encodeAsByteBuffer(request, allocator: ByteBufferAllocator())
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; await client.execute(uri: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;/clowns/&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;id&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;, method: .patch, body: buffer) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        response &lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        response.status
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    @Test &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;testUpdateBoth&lt;/span&gt;() async &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;app&lt;/span&gt; = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; await buildApplication(TestArguments())
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; await app.test(.router) { client &lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;knownGoodID&lt;/span&gt; = &lt;span style=&#34;color:#f5a97f&#34;&gt;4&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;newName&lt;/span&gt; = &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Bozo Jr.&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;newNoseCount&lt;/span&gt; = &lt;span style=&#34;color:#f5a97f&#34;&gt;18&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;beforeClown&lt;/span&gt; = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; await &lt;span style=&#34;color:#f5a97f&#34;&gt;Self&lt;/span&gt;.&lt;span style=&#34;color:#c6a0f6&#34;&gt;get&lt;/span&gt;(id: knownGoodID, client: client)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;clown&lt;/span&gt; = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; await &lt;span style=&#34;color:#f5a97f&#34;&gt;Self&lt;/span&gt;.patch(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          id: knownGoodID, name: newName, spareNoses: newNoseCount, client: client)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        #expect(clown &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;!=&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;nil&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        #expect(clown!.name == newName)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        #expect(clown!.spareNoses == newNoseCount)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        #expect(clown!.name &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;!=&lt;/span&gt; beforeClown?.name)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        #expect(clown!.spareNoses &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;!=&lt;/span&gt; beforeClown?.spareNoses)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        #expect(clown!.id == beforeClown?.id)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;retrievedClown&lt;/span&gt; = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; await &lt;span style=&#34;color:#f5a97f&#34;&gt;Self&lt;/span&gt;.&lt;span style=&#34;color:#c6a0f6&#34;&gt;get&lt;/span&gt;(id: clown!.id, client: client)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        #expect(clown == retrievedClown)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;retrievedOrigIDClown&lt;/span&gt; = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; await &lt;span style=&#34;color:#f5a97f&#34;&gt;Self&lt;/span&gt;.&lt;span style=&#34;color:#c6a0f6&#34;&gt;get&lt;/span&gt;(id: knownGoodID, client: client)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        #expect(retrievedClown == retrievedOrigIDClown)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    @Test &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;testUpdateBadId&lt;/span&gt;() async &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;app&lt;/span&gt; = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; await buildApplication(TestArguments())
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; await app.test(.router) { client &lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;knownBadID&lt;/span&gt; = &lt;span style=&#34;color:#f5a97f&#34;&gt;890_379_023&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;newName&lt;/span&gt; = &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Bozo Jr.&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;newNoseCount&lt;/span&gt; = &lt;span style=&#34;color:#f5a97f&#34;&gt;18&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;_&lt;/span&gt; = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; await client.execute(uri: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;/clowns/&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;knownBadID&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;, method: .&lt;span style=&#34;color:#c6a0f6&#34;&gt;get&lt;/span&gt;) { response &lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//bad interpretation of a nil&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          #expect(response.status == .noContent)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;updateStatus&lt;/span&gt; = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; await &lt;span style=&#34;color:#f5a97f&#34;&gt;Self&lt;/span&gt;.patchResponseStatus(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          id: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;knownBadID&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;, name: newName, spareNoses: newNoseCount, client: client)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        #expect(updateStatus == .badRequest)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        updateStatus = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; await &lt;span style=&#34;color:#f5a97f&#34;&gt;Self&lt;/span&gt;.patchResponseStatus(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          id: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;fgu8ik56gw3R)&amp;#34;&lt;/span&gt;, name: newName, spareNoses: newNoseCount, client: client)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        #expect(updateStatus == .badRequest)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    @Test &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;testNoseDecrement&lt;/span&gt;() async &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;app&lt;/span&gt; = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; await buildApplication(TestArguments())
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; await app.test(.router) { client &lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;knownGoodID&lt;/span&gt; = &lt;span style=&#34;color:#f5a97f&#34;&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;beforeClown&lt;/span&gt; = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; await &lt;span style=&#34;color:#f5a97f&#34;&gt;Self&lt;/span&gt;.&lt;span style=&#34;color:#c6a0f6&#34;&gt;get&lt;/span&gt;(id: knownGoodID, client: client)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          #expect(beforeClown &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;!=&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;nil&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;replyClown&lt;/span&gt;:Clown? = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; await client.execute(uri: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;clowns/&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;knownGoodID&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;/honk&amp;#34;&lt;/span&gt;, method: .patch) { response &lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; response.body.readableBytes &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;0&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//print(String(buffer: response.body))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; JSONDecoder().decode(Clown.&lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;, from: response.body)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            } &lt;span style=&#34;color:#c6a0f6&#34;&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;nil&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          #expect(replyClown &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;!=&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;nil&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          #expect(replyClown!.name == beforeClown?.name )
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          #expect(replyClown!.spareNoses &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;!=&lt;/span&gt; beforeClown?.spareNoses)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          #expect(replyClown!.spareNoses &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;+&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;1&lt;/span&gt; == beforeClown?.spareNoses)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          #expect(replyClown!.id == beforeClown?.id)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    @Test &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;testUpdateName&lt;/span&gt;() async &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;app&lt;/span&gt; = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; await buildApplication(TestArguments())
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; await app.test(.router) { client &lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;knownGoodID&lt;/span&gt; = &lt;span style=&#34;color:#f5a97f&#34;&gt;4&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;newName&lt;/span&gt; = &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Bozo Jr.&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;beforeClown&lt;/span&gt; = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; await &lt;span style=&#34;color:#f5a97f&#34;&gt;Self&lt;/span&gt;.&lt;span style=&#34;color:#c6a0f6&#34;&gt;get&lt;/span&gt;(id: knownGoodID, client: client)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;clown&lt;/span&gt; = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; await &lt;span style=&#34;color:#f5a97f&#34;&gt;Self&lt;/span&gt;.patch(id: knownGoodID, name: newName, client: client)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        #expect(clown &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;!=&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;nil&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        #expect(clown!.name == newName)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        #expect(clown!.name &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;!=&lt;/span&gt; beforeClown?.name)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        #expect(clown!.spareNoses == beforeClown?.spareNoses)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        #expect(clown!.id == beforeClown?.id)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;retrievedClown&lt;/span&gt; = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; await &lt;span style=&#34;color:#f5a97f&#34;&gt;Self&lt;/span&gt;.&lt;span style=&#34;color:#c6a0f6&#34;&gt;get&lt;/span&gt;(id: clown!.id, client: client)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        #expect(clown == retrievedClown)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;retrievedOrigIDClown&lt;/span&gt; = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; await &lt;span style=&#34;color:#f5a97f&#34;&gt;Self&lt;/span&gt;.&lt;span style=&#34;color:#c6a0f6&#34;&gt;get&lt;/span&gt;(id: knownGoodID, client: client)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        #expect(retrievedClown == retrievedOrigIDClown)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;delete&#34;&gt;Delete&lt;/h3&gt;
&lt;h4 id=&#34;controller-3&#34;&gt;Controller&lt;/h4&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;/// Delete clown endpoint&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  @Sendable &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;delete&lt;/span&gt;(request: Request, context: some RequestContext) async &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    -&amp;gt; HTTPResponse.Status
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;id&lt;/span&gt; = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; context.parameters.require(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;id&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#c6a0f6&#34;&gt;as&lt;/span&gt;: &lt;span style=&#34;color:#91d7e3&#34;&gt;Int&lt;/span&gt;.&lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; await &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;.repository.delete(id: id) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; .ok
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    } &lt;span style=&#34;color:#c6a0f6&#34;&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; .badRequest
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;/// Delete all clowns endpoint&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  @Sendable &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;deleteAll&lt;/span&gt;(request: Request, context: some RequestContext) async &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    -&amp;gt; HTTPResponse.Status
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; await &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;.repository.deleteAll()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; .ok
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h4 id=&#34;tests-3&#34;&gt;Tests&lt;/h4&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// also uses Self.get&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;delete&lt;/span&gt;(id: &lt;span style=&#34;color:#91d7e3&#34;&gt;Int&lt;/span&gt;, client: some TestClientProtocol) async &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; -&amp;gt; HTTPResponse.Status
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; await client.execute(uri: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;/clowns/&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;id&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;, method: .delete) { response &lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        response.status
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;deleteAll&lt;/span&gt;(client: some TestClientProtocol) async &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; -&amp;gt; HTTPResponse.Status {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; await client.execute(uri: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;/clowns&amp;#34;&lt;/span&gt;, method: .delete) { response &lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        response.status
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    @Test &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;testDelete&lt;/span&gt;() async &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;app&lt;/span&gt; = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; await buildApplication(TestArguments())
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; await app.test(.router) { client &lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;knownGoodID&lt;/span&gt; = &lt;span style=&#34;color:#f5a97f&#34;&gt;4&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;beforeClown&lt;/span&gt; = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; await &lt;span style=&#34;color:#f5a97f&#34;&gt;Self&lt;/span&gt;.&lt;span style=&#34;color:#c6a0f6&#34;&gt;get&lt;/span&gt;(id: knownGoodID, client: client)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        #expect(beforeClown &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;!=&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;nil&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;status&lt;/span&gt; = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; await &lt;span style=&#34;color:#f5a97f&#34;&gt;Self&lt;/span&gt;.delete(id: knownGoodID, client: client)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        #expect(status == .ok)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; await client.execute(uri: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;/clowns/&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;knownGoodID&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;, method: .&lt;span style=&#34;color:#c6a0f6&#34;&gt;get&lt;/span&gt;) { response &lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//bad interpretation of a nil&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          #expect(response.status == .noContent)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; await client.execute(uri: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;/clowns/&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;knownGoodID&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;, method: .delete) { response &lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          #expect(response.status == .badRequest)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    @Test &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;testDeleteAll&lt;/span&gt;() async &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;app&lt;/span&gt; = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; await buildApplication(TestArguments())
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; await app.test(.router) { client &lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;knownGoodID&lt;/span&gt; = &lt;span style=&#34;color:#f5a97f&#34;&gt;4&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;beforeClown&lt;/span&gt; = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; await &lt;span style=&#34;color:#f5a97f&#34;&gt;Self&lt;/span&gt;.&lt;span style=&#34;color:#c6a0f6&#34;&gt;get&lt;/span&gt;(id: knownGoodID, client: client)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        #expect(beforeClown &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;!=&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;nil&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;status&lt;/span&gt; = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; await &lt;span style=&#34;color:#f5a97f&#34;&gt;Self&lt;/span&gt;.deleteAll(client: client)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        #expect(status == .ok)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; await client.execute(uri: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;/clowns/&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;knownGoodID&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;, method: .&lt;span style=&#34;color:#c6a0f6&#34;&gt;get&lt;/span&gt;) { response &lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//bad interpretation of a nil&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          #expect(response.status == .noContent)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; await client.execute(uri: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;/clowns/&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;knownGoodID&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;, method: .delete) { response &lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          #expect(response.status == .badRequest)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;deletedClowns&lt;/span&gt; = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; await &lt;span style=&#34;color:#f5a97f&#34;&gt;Self&lt;/span&gt;.list(client: client)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        #expect(deletedClowns.&lt;span style=&#34;color:#91d7e3&#34;&gt;isEmpty&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;left-to-do&#34;&gt;Left to do&lt;/h3&gt;
&lt;p&gt;I would rate this controller as &amp;ldquo;needs improvement&amp;rdquo;, especially on the error handling. Everywhere there&amp;rsquo;s a&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;throw&lt;/span&gt; HTTPError(.badRequest)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;for example, there ought to be a message providing more data.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;throw&lt;/span&gt; HTTPError(.badRequest, message: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;this this you sent didn&amp;#39;t make it through&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;When a call like&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;honkRequestID&lt;/span&gt; = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; context.parameters.require(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;id&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#c6a0f6&#34;&gt;as&lt;/span&gt;: &lt;span style=&#34;color:#91d7e3&#34;&gt;Int&lt;/span&gt;.&lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;fails, Hummingbird will catch the error and wrap it in it&amp;rsquo;s own preferred HTTPStatus with an informative response body. I should add my own&lt;/p&gt;
&lt;p&gt;When trying to match an API that doesn&amp;rsquo;t use the same response statuses as the Hummingbird defaults, it may mean catching that error in the closure and implementing your own Error -&amp;gt; HTTPResponse handling.&lt;/p&gt;
&lt;p&gt;Also, where is the Authentication and Authorization layer? Can anyone delete anything??!!!&lt;/p&gt;
&lt;p&gt;There is definitely more to do.&lt;/p&gt;
&lt;h2 id=&#34;summary&#34;&gt;Summary&lt;/h2&gt;
&lt;p&gt;It takes a bit of fiddling to implement a CRUD the first time in Hummingbird, but I&amp;rsquo;ve written a couple of others already mostly by copy-pasting and searching for my Type name. Seems like a potential macro or something could be written, @CRUDable, ha! To do that correctly would pretty much be reimplementing &lt;a href=&#34;https://whynotestflight.com/excuses/swiftdata-my-first-look/&#34;&gt;SwiftData&lt;/a&gt; so perhaps not this week.&lt;/p&gt;
&lt;p&gt;A way to make writing API code that&amp;rsquo;s very enforceable across projects is to use the &lt;a href=&#34;https://www.openapis.org&#34;&gt;OpenAPI&lt;/a&gt; &lt;a href=&#34;https://github.com/apple/swift-openapi-generator&#34;&gt;plugin for Swift packages&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;In the next post we&amp;rsquo;ll start the process of implementing the Clown JSON API with that.&lt;/p&gt;
</description>
    </item>
    
    
    
    <item>
      <title>How do I get Hummingbird to use Mustache templates instead?</title>
      <link>https://whynotestflight.com/excuses/how-do-i-get-hummingbird-to-use-mustache-templates-instead/</link>
      <pubDate>Wed, 17 Sep 2025 00:00:00 +0000</pubDate>
      
      <guid>https://whynotestflight.com/excuses/how-do-i-get-hummingbird-to-use-mustache-templates-instead/</guid>
      <description>&lt;p&gt;As mentioned last post, there are lots of ways to &lt;a href=&#34;https://swiftpackageindex.com/search?query=HTML&#34;&gt;generate HTML&lt;/a&gt; with Swift, if that&amp;rsquo;s how working with HTML works for you.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;m perhaps a little old school and am more used to working with templates and template engines for web stuff. (Although I suppose there&amp;rsquo;s no reason not to write a &lt;a href=&#34;https://whynotestflight.com/excuses/what-if-instead-of-a-cli-plugins-part-1-command-plugins/&#34;&gt;command plugin&lt;/a&gt; to generate those templates for you.)&lt;/p&gt;
&lt;p&gt;So I was pretty happy that the Hummingbird project already had a solution for that, the &lt;a href=&#34;https://swiftpackageindex.com/hummingbird-project/swift-mustache&#34;&gt;swift-mustache&lt;/a&gt; library. While it&amp;rsquo;s part of the Hummingbird Project ecosystem, it doesn&amp;rsquo;t require Hummingbird to use it.&lt;/p&gt;
&lt;p&gt;This example and the hand-written HTML one are available at&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/carlynorama/HummingbirdExamples/tree/main/04_html_responses&#34;&gt;https://github.com/carlynorama/HummingbirdExamples/tree/main/04_html_responses&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;resources&#34;&gt;Resources&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://mustache.github.io&#34;&gt;https://mustache.github.io&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://en.wikipedia.org/wiki/Mustache_(template_system)&#34;&gt;https://en.wikipedia.org/wiki/Mustache_(template_system)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://swiftpackageindex.com/hummingbird-project/swift-mustache&#34;&gt;https://swiftpackageindex.com/hummingbird-project/swift-mustache&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://swiftonserver.com/templating-with-swift-mustache/&#34;&gt;https://swiftonserver.com/templating-with-swift-mustache/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://swifttoolkit.dev/posts/swift-mustache&#34;&gt;https://swifttoolkit.dev/posts/swift-mustache&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;There are also several examples in the official &lt;a href=&#34;https://github.com/search?q=repo%3Ahummingbird-project%2Fhummingbird-examples%20mustache&amp;amp;type=code&#34;&gt;Hummingbird examples repo&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&#34;packageswift--directory-structure-changes&#34;&gt;Package.swift &amp;amp; Directory Structure Changes&lt;/h3&gt;
&lt;p&gt;To work with swift-mustache, first add the dependency&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## from dir with the Package.swift&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## add the dependency&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;swift package add-dependency https://github.com/hummingbird-project/swift-mustache --from 2.0.0
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## make the folder&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;mkdir -p Sources/Templates
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The &lt;code&gt;Package.swift&lt;/code&gt; will have to be updated by hand to add the dependency to the executable, and to create a &lt;code&gt;Resources&lt;/code&gt; folder so the template files will be seen by the build process and be incorporated in the bundle.(Another option includes an absolute path when initializing the &lt;code&gt;MustacheLibrary&lt;/code&gt; instance)&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// swift-tools-version:6.2&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;PackageDescription&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;package&lt;/span&gt; = Package(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    name: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;htmlResponses&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    platforms : [.macOS(.v14)],
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    products: [.executable(name: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;htmlResponses&amp;#34;&lt;/span&gt;, targets: [&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;htmlResponses&amp;#34;&lt;/span&gt;])],
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    dependencies: [
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        .package(url: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;https://github.com/hummingbird-project/hummingbird.git&amp;#34;&lt;/span&gt;, from: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;2.0.0&amp;#34;&lt;/span&gt;),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        .package(url: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;https://github.com/apple/swift-argument-parser.git&amp;#34;&lt;/span&gt;, from: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;1.3.0&amp;#34;&lt;/span&gt;),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        .package(url: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;https://github.com/hummingbird-project/swift-mustache&amp;#34;&lt;/span&gt;, from: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;2.0.0&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    ],
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    targets: [
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        .executableTarget(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            name: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;htmlResponses&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            dependencies: [
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                .product(name: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;ArgumentParser&amp;#34;&lt;/span&gt;, package: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;swift-argument-parser&amp;#34;&lt;/span&gt;),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                .product(name: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Hummingbird&amp;#34;&lt;/span&gt;, package: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;hummingbird&amp;#34;&lt;/span&gt;),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                .product(name: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Mustache&amp;#34;&lt;/span&gt;, package: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;swift-mustache&amp;#34;&lt;/span&gt;),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            ],
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            resources: [.process(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Templates&amp;#34;&lt;/span&gt;)]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        ),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        .testTarget(name: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;addTestingTests&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            dependencies: [
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                .byName(name: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;htmlResponses&amp;#34;&lt;/span&gt;),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                .product(name: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;HummingbirdTesting&amp;#34;&lt;/span&gt;, package: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;hummingbird&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            ],
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            path: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Tests/AppTests&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        )
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    ]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;the-templates&#34;&gt;The Templates&lt;/h3&gt;
&lt;p&gt;Next make a couple of simple templates to chuck into that folder.&lt;/p&gt;
&lt;p&gt;This example uses two super short template, mostly just to show how to combine two templates.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;base.mustache&lt;/code&gt; (first) calls &lt;code&gt;body.mustache&lt;/code&gt; with the line &lt;code&gt;{{&amp;gt; body }}&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;body.mustache&lt;/code&gt; is referred to as a &lt;a href=&#34;https://mustache.github.io/mustache.5.html#Partials&#34;&gt;Partial&lt;/a&gt;. A nice little demo is on this &lt;a href=&#34;https://jgonggrijp.gitlab.io/wontache/playground.html&#34;&gt;mustache playground&lt;/a&gt;.&lt;/p&gt;
&lt;h4 id=&#34;basemustache&#34;&gt;base.mustache&lt;/h4&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-HTML&#34; data-lang=&#34;HTML&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&amp;lt;!DOCTYPE html&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;html&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;head&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &amp;lt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;title&lt;/span&gt;&amp;gt;{{  title  }}&amp;lt;/&lt;span style=&#34;color:#c6a0f6&#34;&gt;title&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &amp;lt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;meta&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;charset&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;UTF-8&amp;#34;&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;/&lt;span style=&#34;color:#c6a0f6&#34;&gt;head&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{{&amp;gt; body }}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;/&lt;span style=&#34;color:#c6a0f6&#34;&gt;html&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h4 id=&#34;bodymustache&#34;&gt;body.mustache&lt;/h4&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-HTML&#34; data-lang=&#34;HTML&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;body&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;p&lt;/span&gt;&amp;gt;__________{{  message  }}__________________________&amp;lt;/&lt;span style=&#34;color:#c6a0f6&#34;&gt;p&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;p&lt;/span&gt;&amp;gt;&amp;lt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;a&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;href&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;/&amp;#34;&lt;/span&gt;&amp;gt;back to home&amp;lt;/&lt;span style=&#34;color:#c6a0f6&#34;&gt;a&lt;/span&gt;&amp;gt;.&amp;lt;/&lt;span style=&#34;color:#c6a0f6&#34;&gt;p&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;/&lt;span style=&#34;color:#c6a0f6&#34;&gt;body&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;That&amp;rsquo;s it! Notice the double curlies? &lt;code&gt;{{...}}&lt;/code&gt;? &lt;a href=&#34;https://gohugo.io/templates/types/#article&#34;&gt;hugo uses those too&lt;/a&gt;! (see [meta]/tags/meta/), as does the compatible JS library, &lt;a href=&#34;https://handlebarsjs.com&#34;&gt;Handlebars&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;While what&amp;rsquo;s in them will be different partially because &lt;a href=&#34;https://stackoverflow.com/a/11766634&#34;&gt;Mustache is logic-less&lt;/a&gt;, the familiarity is nice.&lt;/p&gt;
&lt;h3 id=&#34;the-type&#34;&gt;The Type&lt;/h3&gt;
&lt;p&gt;Once the templates exist, a type that will process them and turn them into a &lt;code&gt;Response&lt;/code&gt; comes next.&lt;/p&gt;
&lt;p&gt;The main difference between &lt;code&gt;AcrobatHTML&lt;/code&gt; and &lt;a href=&#34;https://whynotestflight.com/excuses/how-do-i-get-hummingbird-to-serve-html-dynamically/#organplayerhtmlswift&#34;&gt;&lt;code&gt;OrganPlayerHTML&lt;/code&gt;&lt;/a&gt; will be the need to have a reference to a Mustache library and call to the &lt;a href=&#34;https://github.com/hummingbird-project/swift-mustache/blob/999fda1e52173f949a135ecb55aa46a36843a68b/Sources/Mustache/Library.swift#L85&#34;&gt;&lt;code&gt;library.render&lt;/code&gt;&lt;/a&gt; function that pulls all the templates together.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;Hummingbird&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#if&lt;/span&gt; &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;canImport&lt;/span&gt;(&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;FoundationEssentials&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;FoundationEssentials&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#else&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;Foundation&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#endif&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;Mustache&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//struct with all the needed info for the template. &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//struct parameters must match names in the templates.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;BasicInfo&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;title&lt;/span&gt;: &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;message&lt;/span&gt;: &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;AcrobatHTML&lt;/span&gt;:ResponseGenerator  {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// load mustache template library&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;message&lt;/span&gt;: &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;library&lt;/span&gt;: MustacheLibrary
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;init&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; message: &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;, library:MustacheLibrary) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;.message = message
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;.library = library
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;private&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;html&lt;/span&gt;:&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;result&lt;/span&gt; = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt;? render() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; result
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        } &lt;span style=&#34;color:#c6a0f6&#34;&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;??? oops.&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;private&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;render&lt;/span&gt;() &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; -&amp;gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;? {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;messagePost&lt;/span&gt; = BasicInfo(title: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;I&amp;#39;m a Message!&amp;#34;&lt;/span&gt;, message: message)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//func render(_ object: Any, withTemplate name: String, reload: Bool)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;rendered&lt;/span&gt; = library.render(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            messagePost,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            withTemplate: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;base&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        )
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; rendered
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;response&lt;/span&gt;(from request: Request, context: some RequestContext) &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; -&amp;gt; Response {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;buffer&lt;/span&gt; = ByteBuffer(string: &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;.html)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; .&lt;span style=&#34;color:#ed8796&#34;&gt;init&lt;/span&gt;(status: .ok, headers: [.contentType: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;text/html&amp;#34;&lt;/span&gt;], body: .&lt;span style=&#34;color:#ed8796&#34;&gt;init&lt;/span&gt;(byteBuffer: buffer))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The object &amp;ldquo;BasicInfo&amp;rdquo; will then be passed to &lt;a href=&#34;https://github.com/hummingbird-project/swift-mustache/blob/999fda1e52173f949a135ecb55aa46a36843a68b/Sources/Mustache/Template%2BRender.swift#L24&#34;&gt;base.mustache&amp;rsquo;s render function&lt;/a&gt;, which will recurse through any nested templates, matching up the &lt;a href=&#34;https://github.com/hummingbird-project/swift-mustache/blob/999fda1e52173f949a135ecb55aa46a36843a68b/Sources/Mustache/Template.swift#L69&#34;&gt;tokenized information&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;It&amp;rsquo;s a nice implementation of a render that could be fun to go through more completely in a future post! (a bit more on &lt;a href=&#34;https://en.wikipedia.org/wiki/Lexical_analysis#Token&#34;&gt;Lexical tokens&lt;/a&gt;, which I talked about a little bit [here]({{ relref 20240327-string-scanning }}), but there is much to say.)&lt;/p&gt;
&lt;h3 id=&#34;creating-the-library-instance--adding-the-route&#34;&gt;Creating the Library Instance &amp;amp; Adding the Route&lt;/h3&gt;
&lt;p&gt;In this example the Mustache Library will be created in &lt;code&gt;Application+build.swift&lt;/code&gt; in the &lt;code&gt;buildRouter&lt;/code&gt; function.&lt;/p&gt;
&lt;p&gt;As mentioned above, the templates are being put in the bundle, rather than in some absolute path on the local machine.&lt;/p&gt;
&lt;p&gt;The suggested &lt;a href=&#34;https://github.com/hummingbird-project/hummingbird-examples/blob/9f4202f2a384caa5f5f3f7c5c37ea70230cbef46/webauthn/Dockerfile&#34;&gt;docker files&lt;/a&gt; all have a line for moving things that are in the bundle&amp;rsquo;s resource folder&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-dockerfile&#34; data-lang=&#34;dockerfile&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# Copy resources bundled by SPM to staging area&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;RUN&lt;/span&gt; find -L &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;$(&lt;/span&gt;swift build --package-path /build -c release --show-bin-path&lt;span style=&#34;color:#c6a0f6&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;/&amp;#34;&lt;/span&gt; -regex &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#39;.*\.resources$&amp;#39;&lt;/span&gt; -exec cp -Ra &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;{}&lt;/span&gt; ./ &lt;span style=&#34;color:#8aadf4&#34;&gt;\;&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;so the transition to a containerized run should go smoothly.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//ADD TO TOP WITH OTHER IMPORTS&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#if&lt;/span&gt; &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;canImport&lt;/span&gt;(&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;FoundationEssentials&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;FoundationEssentials&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#else&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;Foundation&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#endif&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;Mustache&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;buildRouter&lt;/span&gt;() async &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; -&amp;gt; Router&amp;lt;AppRequestContext&amp;gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;router&lt;/span&gt; = Router(context: AppRequestContext.&lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;mustacheLibrary&lt;/span&gt; = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; await MustacheLibrary(directory: Bundle.module.resourcePath!)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//let mustacheLibrary = MustacheLibrary()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    router.&lt;span style=&#34;color:#c6a0f6&#34;&gt;get&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;/acrobat&amp;#34;&lt;/span&gt;) { &lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt;, &lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;not here&amp;#34;&lt;/span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    router.&lt;span style=&#34;color:#c6a0f6&#34;&gt;get&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;acrobat/:message&amp;#34;&lt;/span&gt;) { &lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt;, context &lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;guard&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;message&lt;/span&gt; = context.parameters.&lt;span style=&#34;color:#c6a0f6&#34;&gt;get&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;message&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#c6a0f6&#34;&gt;as&lt;/span&gt;: &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;.&lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;) &lt;span style=&#34;color:#c6a0f6&#34;&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;throw&lt;/span&gt; HTTPError(.badRequest, &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;could not read a message from the data provided&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;decoded&lt;/span&gt; = message.removingPercentEncoding ?? &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;can&amp;#39;t-balance-here&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; AcrobatHTML(decoded, library: mustacheLibrary)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;the-call&#34;&gt;The Call&lt;/h3&gt;
&lt;p&gt;Back in the public folder, we can add the link to the index.html file.&lt;/p&gt;
&lt;p&gt;Don&amp;rsquo;t forget to percent encode the string!&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-HTML&#34; data-lang=&#34;HTML&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&amp;lt;!DOCTYPE html&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;html&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;head&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &amp;lt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;title&lt;/span&gt;&amp;gt;Test Webpage: Site Index Page&amp;lt;/&lt;span style=&#34;color:#c6a0f6&#34;&gt;title&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &amp;lt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;meta&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;charset&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;UTF-8&amp;#34;&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;/&lt;span style=&#34;color:#c6a0f6&#34;&gt;head&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;body&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &amp;lt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;li&lt;/span&gt;&amp;gt;These links return generated HTML pages as their response bodies&amp;lt;/&lt;span style=&#34;color:#c6a0f6&#34;&gt;li&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &amp;lt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;ul&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &amp;lt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;li&lt;/span&gt;&amp;gt;&amp;lt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;a&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;href&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;/organ/LaTaDadaDadaLaTaDaDah&lt;/span&gt;&amp;gt;organ music&amp;lt;/&lt;span style=&#34;color:#c6a0f6&#34;&gt;a&lt;/span&gt;&amp;gt;&amp;lt;/&lt;span style=&#34;color:#c6a0f6&#34;&gt;li&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &amp;lt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;li&lt;/span&gt;&amp;gt;&amp;lt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;a&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;href&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;/acrobat/not%20gonna%20fall&lt;/span&gt;&amp;gt;acrobat&amp;lt;/&lt;span style=&#34;color:#c6a0f6&#34;&gt;a&lt;/span&gt;&amp;gt;&amp;lt;/&lt;span style=&#34;color:#c6a0f6&#34;&gt;li&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &amp;lt;/&lt;span style=&#34;color:#c6a0f6&#34;&gt;ul&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &amp;lt;/&lt;span style=&#34;color:#c6a0f6&#34;&gt;li&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;/&lt;span style=&#34;color:#c6a0f6&#34;&gt;body&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;/&lt;span style=&#34;color:#c6a0f6&#34;&gt;html&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;add-some-testing&#34;&gt;Add some testing&lt;/h3&gt;
&lt;p&gt;Different routes mean &lt;a href=&#34;https://github.com/carlynorama/HummingbirdExamples/tree/main/04_html_responses/htmlResponses/Tests/AppTests&#34;&gt;different tests&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;These are pretty minimal tests. They just make sure the routes exist with a known happy path.&lt;/p&gt;
&lt;p&gt;Unhappy paths, valid HTML headers, valid HTML, that the content is in there as expected are all things one might test in a more comprehensive suite.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;AppTests&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;TestArguments&lt;/span&gt;: AppArguments {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;nameTag&lt;/span&gt;: &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt; = &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;nwtTestServer&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;hostname&lt;/span&gt; = &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;127.0.0.1&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;port&lt;/span&gt; = &lt;span style=&#34;color:#f5a97f&#34;&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;logLevel&lt;/span&gt;: Logger.Level? = .trace
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    @Test &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;testCreateApp&lt;/span&gt;() async &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;app&lt;/span&gt; = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; await buildApplication(TestArguments())
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; await app.test(.router) { client &lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;_&lt;/span&gt; = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; await client.execute(uri: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;/ping&amp;#34;&lt;/span&gt;, method: .&lt;span style=&#34;color:#c6a0f6&#34;&gt;get&lt;/span&gt;) { response &lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                #expect(response.status == .ok)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    @Test &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;testOrgan&lt;/span&gt;() async &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    	&lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;app&lt;/span&gt; = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; await buildApplication(TestArguments())
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; await app.test(.router) { client &lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        	&lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;message&lt;/span&gt; = &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;my%20precent%20encoded%20Message&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;_&lt;/span&gt; = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; await client.execute(uri: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;/organ/&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;message&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;, method: .&lt;span style=&#34;color:#c6a0f6&#34;&gt;get&lt;/span&gt;) { response &lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                #expect(response.status == .ok)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    @Test &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;testAcrobat&lt;/span&gt;() async &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;app&lt;/span&gt; = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; await buildApplication(TestArguments())
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; await app.test(.router) { client &lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        	&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//http://localhost:8080/acrobat/not%20gonna%20fall&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        	&lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;message&lt;/span&gt; = &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;my%20precent%20encoded%20Message&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;_&lt;/span&gt; = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; await client.execute(uri: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;/acrobat/&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;message&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;, method: .&lt;span style=&#34;color:#c6a0f6&#34;&gt;get&lt;/span&gt;) { response &lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                #expect(response.status == .ok)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;summary&#34;&gt;Summary&lt;/h2&gt;
&lt;p&gt;That&amp;rsquo;s quick overview of how to get the bare minimum working with Mustache templates. The next post will be about making a &lt;a href=&#34;https://en.wikipedia.org/wiki/Create,_read,_update_and_delete&#34;&gt;CRUD&lt;/a&gt; interface for a codable type by hand, and the one after that will compare it to using the &lt;a href=&#34;https://www.openapis.org&#34;&gt;OpenAPI&lt;/a&gt; &lt;a href=&#34;https://github.com/apple/swift-openapi-generator&#34;&gt;plugin for Swift packages&lt;/a&gt;.&lt;/p&gt;
</description>
    </item>
    
    
    
    <item>
      <title>How do I get Hummingbird to serve html dynamically?</title>
      <link>https://whynotestflight.com/excuses/how-do-i-get-hummingbird-to-serve-html-dynamically/</link>
      <pubDate>Tue, 16 Sep 2025 00:00:00 +0000</pubDate>
      
      <guid>https://whynotestflight.com/excuses/how-do-i-get-hummingbird-to-serve-html-dynamically/</guid>
      <description>&lt;p&gt;Most the examples so far focus on returning data or simple strings, but what if instead I wanted an actual HTML response generated programmatically?&lt;/p&gt;
&lt;p&gt;This post will show simply wrapping a string of known-good HTML and in a response. The next post using a Mustache template. The combined example is available:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/carlynorama/HummingbirdExamples/tree/main/04_html_responses&#34;&gt;https://github.com/carlynorama/HummingbirdExamples/tree/main/04_html_responses&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;organplayerhtmlswift&#34;&gt;OrganPlayerHTML.swift&lt;/h3&gt;
&lt;p&gt;I snagged the html string -&amp;gt; http response wrapper code for this from &lt;a href=&#34;https://github.com/search?q=repo%3Ahummingbird-project%2Fhummingbird-examples+html.swift&amp;amp;type=code&#34;&gt;the hummingbird examples repo&lt;/a&gt;, but made it a type that would accept a &amp;ldquo;message&amp;rdquo; String.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;Hummingbird&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;OrganPlayerHTML&lt;/span&gt;: ResponseGenerator {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;message&lt;/span&gt;: &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;init&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; message: &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;.message = message
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;private&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;html&lt;/span&gt;:&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f5a97f&#34;&gt;Self&lt;/span&gt;.generateHTMLForMessage(message)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;response&lt;/span&gt;(from request: Request, context: some RequestContext) &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; -&amp;gt; Response {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;buffer&lt;/span&gt; = ByteBuffer(string: &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;.html)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; .&lt;span style=&#34;color:#ed8796&#34;&gt;init&lt;/span&gt;(status: .ok, headers: [.contentType: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;text/html&amp;#34;&lt;/span&gt;], body: .&lt;span style=&#34;color:#ed8796&#34;&gt;init&lt;/span&gt;(byteBuffer: buffer))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;generateHTMLForMessage&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; message:&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;) -&amp;gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&amp;#34;&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;        &amp;lt;!DOCTYPE html&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;        &amp;lt;html&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;        &amp;lt;head&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;            &amp;lt;title&amp;gt;Hear the Music!!!&amp;lt;/title&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;            &amp;lt;meta charset=&amp;#34;&lt;/span&gt;UTF&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;-&lt;/span&gt;&lt;span style=&#34;color:#f5a97f&#34;&gt;8&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;        &amp;lt;/head&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;        &amp;lt;body&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;        &amp;lt;p&amp;gt;&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;message&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;lt;/p&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;        &amp;lt;p&amp;gt;&amp;lt;a href=&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;/&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&amp;gt;back to index&amp;lt;/a&amp;gt;.&amp;lt;/p&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;        &amp;lt;/body&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;        &amp;lt;/html&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;        &amp;#34;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;the-route&#34;&gt;The Route&lt;/h3&gt;
&lt;p&gt;Back in the &lt;code&gt;buildRouter&lt;/code&gt; function in &lt;code&gt;Application+build.swift&lt;/code&gt; one possible route one could use could be:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    router.&lt;span style=&#34;color:#c6a0f6&#34;&gt;get&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;organ/:message&amp;#34;&lt;/span&gt;) { &lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt;, context &lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;guard&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;message&lt;/span&gt; = context.parameters.&lt;span style=&#34;color:#c6a0f6&#34;&gt;get&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;message&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#c6a0f6&#34;&gt;as&lt;/span&gt;: &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;.&lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;) &lt;span style=&#34;color:#c6a0f6&#34;&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;throw&lt;/span&gt; HTTPError(.badRequest, message:&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Could not parse message.&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; OrganPlayerHTML(message)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Don&amp;rsquo;t forget to &lt;a href=&#34;https://perishablepress.com/how-to-write-valid-url-query-string-parameters/&#34;&gt;percent encode any spaces, etc.&lt;/a&gt;&amp;hellip;&lt;/p&gt;
&lt;h3 id=&#34;the-call&#34;&gt;The Call&lt;/h3&gt;
&lt;p&gt;In the public folders&amp;rsquo;s index HTML page a call to that route might look like&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-html&#34; data-lang=&#34;html&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;body&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &amp;lt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;li&lt;/span&gt;&amp;gt;These links return generated HTML pages as their response bodies&amp;lt;/&lt;span style=&#34;color:#c6a0f6&#34;&gt;li&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &amp;lt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;ul&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &amp;lt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;li&lt;/span&gt;&amp;gt;&amp;lt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;a&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;href&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;/organ/LaTaDadaDadaLaTaDaDah&lt;/span&gt;&amp;gt;organ music&amp;lt;/&lt;span style=&#34;color:#c6a0f6&#34;&gt;a&lt;/span&gt;&amp;gt;&amp;lt;/&lt;span style=&#34;color:#c6a0f6&#34;&gt;li&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &amp;lt;/&lt;span style=&#34;color:#c6a0f6&#34;&gt;ul&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &amp;lt;/&lt;span style=&#34;color:#c6a0f6&#34;&gt;li&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;/&lt;span style=&#34;color:#c6a0f6&#34;&gt;body&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;tada&#34;&gt;Tada!&lt;/h3&gt;
&lt;p&gt;&lt;img src=&#34;organ_page.png&#34; alt=&#34;Screenshot of a safari browser window displaying the simple text &amp;ldquo;LaTaDadaDadaLaTaDaDah&amp;rdquo;, which was the same as the text that was in the URL seen in the HTML example. There is also a link back to the site&amp;rsquo;s home page.&#34;&gt;&lt;/p&gt;
&lt;p&gt;Not the most snazzy, but I hope it points to how to use a Hummingbird route to trigger building a simple HTML page for more complicated examples.&lt;/p&gt;
&lt;p&gt;There are MANY swift packages where people create their favorite way to &lt;a href=&#34;https://swiftpackageindex.com/search?query=HTML&#34;&gt;generate HTML&lt;/a&gt;, if the situation is too complex to handle by hand.&lt;/p&gt;
&lt;p&gt;For me my preference would be the Mustache templating engine, which conveniently the Hummingbird Project already has covered.&lt;/p&gt;
&lt;p&gt;Next post!&lt;/p&gt;
</description>
    </item>
    
    
    
    <item>
      <title>How do I test the Hummingbird routes with swift-testing?</title>
      <link>https://whynotestflight.com/excuses/how-do-i-test-the-hummingbird-routes-with-swift-testing/</link>
      <pubDate>Mon, 15 Sep 2025 00:00:00 +0000</pubDate>
      
      <guid>https://whynotestflight.com/excuses/how-do-i-test-the-hummingbird-routes-with-swift-testing/</guid>
      <description>&lt;p&gt;It&amp;rsquo;d be way easier to catch any errors in all those routes if instead of that &lt;a href=&#34;https://whynotestflight.com/excuses/what-kinda-routes-can-i-use-with-hummingbird/#testing-script&#34;&gt;bash script&lt;/a&gt;, we could use &lt;a href=&#34;https://github.com/swiftlang/swift-testing&#34;&gt;swift-testing&lt;/a&gt; instead.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/carlynorama/HummingbirdExamples/tree/main/03_add_testing&#34;&gt;https://github.com/carlynorama/HummingbirdExamples/tree/main/03_add_testing&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://docs.hummingbird.codes/2.0/tutorials/todos#testing-your-application&#34;&gt;https://docs.hummingbird.codes/2.0/tutorials/todos#testing-your-application&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Meet Swift Testing (WWDC 2024): &lt;a href=&#34;https://developer.apple.com/videos/play/wwdc2024/10179/&#34;&gt;https://developer.apple.com/videos/play/wwdc2024/10179/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;apparguments&#34;&gt;AppArguments&lt;/h2&gt;
&lt;p&gt;&lt;a href=&#34;https://github.com/carlynorama/HummingbirdExamples/blob/main/02_basic_responses/simple-respond/Sources/simple-respond/AppArguments.swift&#34;&gt;02_basic_responses&lt;/a&gt; added a file that I didn&amp;rsquo;t mention: AppArguments.swift&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;Hummingbird&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;Logging&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//Allows for different setups for testing server and production server&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;protocol&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;AppArguments&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;nameTag&lt;/span&gt;:&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt; { &lt;span style=&#34;color:#c6a0f6&#34;&gt;get&lt;/span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;hostname&lt;/span&gt;: &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt; { &lt;span style=&#34;color:#c6a0f6&#34;&gt;get&lt;/span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;port&lt;/span&gt;: &lt;span style=&#34;color:#91d7e3&#34;&gt;Int&lt;/span&gt; { &lt;span style=&#34;color:#c6a0f6&#34;&gt;get&lt;/span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;logLevel&lt;/span&gt;: Logger.Level? { &lt;span style=&#34;color:#c6a0f6&#34;&gt;get&lt;/span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This struct beings the process of of allowing a separate testing server or servers with different features and the live server.&lt;/p&gt;
&lt;p&gt;As a demonstration, in the (the todos example)[https://docs.hummingbird.codes/2.0/tutorials/todos#testing-your-application], where I got this data structure from, the testing is done on in-memory data and the live server points to a postgres db.&lt;/p&gt;
&lt;p&gt;An instance of AppArguments can be used at that top of every test as needed to spin up a new server unique to that test. For some testing suites it might make sense to make a group of tests that all point to the same App instance, but &lt;a href=&#34;https://github.com/carlynorama/HummingbirdExamples/blob/main/03_add_testing/nowWithTesting/Tests/AppTests/AppTests.swift&#34;&gt;in this example&lt;/a&gt; each test gets its own little serverlette.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#if&lt;/span&gt; &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;canImport&lt;/span&gt;(&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;FoundationEssentials&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;FoundationEssentials&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#else&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;Foundation&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#endif&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;Hummingbird&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;HummingbirdTesting&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;Logging&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;Testing&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;@testable &lt;span style=&#34;color:#ed8796&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;nowWithTesting&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;AppTests&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;TestArguments&lt;/span&gt;: AppArguments {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;nameTag&lt;/span&gt;: &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt; = &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;nwtTestServer&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;hostname&lt;/span&gt; = &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;127.0.0.1&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;port&lt;/span&gt; = &lt;span style=&#34;color:#f5a97f&#34;&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;logLevel&lt;/span&gt;: Logger.Level? = .trace
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    @Test &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;testCreateApp&lt;/span&gt;() async &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;app&lt;/span&gt; = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; await buildApplication(TestArguments())
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; await app.test(.router) { client &lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;_&lt;/span&gt; = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; await client.execute(uri: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;/ping&amp;#34;&lt;/span&gt;, method: .&lt;span style=&#34;color:#c6a0f6&#34;&gt;get&lt;/span&gt;) { response &lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                #expect(response.status == .ok)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//more follows...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;example-tests&#34;&gt;Example Tests&lt;/h2&gt;
&lt;p&gt;The tests aren&amp;rsquo;t comprehensive and the &amp;ldquo;unhappy paths&amp;rdquo; need improvement on both the server side and the testing side. None the less, these examples provide building blocks for what&amp;rsquo;s needed:&lt;/p&gt;
&lt;h3 id=&#34;goodbye&#34;&gt;/goodbye&lt;/h3&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    @Test &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;testGoodbye&lt;/span&gt;() async &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;app&lt;/span&gt; = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; await buildApplication(TestArguments())
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; await app.test(.router) { client &lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;_&lt;/span&gt; = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; await client.execute(uri: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;/goodbye&amp;#34;&lt;/span&gt;, method: .&lt;span style=&#34;color:#c6a0f6&#34;&gt;get&lt;/span&gt;) { response &lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                #expect(response.status == .ok)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                #expect(&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;(buffer: response.body) == &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Ciao!&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;single-wildcard&#34;&gt;Single wildcard&lt;/h3&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    @Test &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;testSingleWild&lt;/span&gt;() async &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;app&lt;/span&gt; = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; await buildApplication(TestArguments())
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; await app.test(.router) { client &lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;_&lt;/span&gt; = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; await client.execute(uri: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;/files/&amp;#34;&lt;/span&gt;, method: .&lt;span style=&#34;color:#c6a0f6&#34;&gt;get&lt;/span&gt;) { response &lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                #expect(response.status == .notFound)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;_&lt;/span&gt; = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; await client.execute(uri: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;/files/testPhrase&amp;#34;&lt;/span&gt;, method: .&lt;span style=&#34;color:#c6a0f6&#34;&gt;get&lt;/span&gt;) { response &lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                #expect(response.status == .ok)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                #expect(&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;(buffer: response.body) == &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;/files/testPhrase&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;_&lt;/span&gt; = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; await client.execute(uri: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;/files/too/many/things&amp;#34;&lt;/span&gt;, method: .&lt;span style=&#34;color:#c6a0f6&#34;&gt;get&lt;/span&gt;) { response &lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                #expect(response.status == .notFound)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;user-route&#34;&gt;/user route&lt;/h3&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    @Test &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;testUser&lt;/span&gt;() async &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;app&lt;/span&gt; = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; await buildApplication(TestArguments())
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; await app.test(.router) { client &lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;_&lt;/span&gt; = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; await client.execute(uri: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;/user/garbfjfesage&amp;#34;&lt;/span&gt;, method: .&lt;span style=&#34;color:#c6a0f6&#34;&gt;get&lt;/span&gt;) { response &lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                #expect(response.status == .badRequest)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;intToTest&lt;/span&gt; = &lt;span style=&#34;color:#f5a97f&#34;&gt;43&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;_&lt;/span&gt; = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; await client.execute(uri: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;/user/&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;intToTest&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;, method: .&lt;span style=&#34;color:#c6a0f6&#34;&gt;get&lt;/span&gt;) { response &lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                #expect(response.status == .ok)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                #expect(&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;(buffer: response.body) == &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;intToTest&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            intToTest = &lt;span style=&#34;color:#f5a97f&#34;&gt;43131&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;_&lt;/span&gt; = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; await client.execute(uri: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;/user/&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;intToTest&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;, method: .&lt;span style=&#34;color:#c6a0f6&#34;&gt;get&lt;/span&gt;) { response &lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                #expect(response.status == .ok)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                #expect(&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;(buffer: response.body) == &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;intToTest&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            intToTest = &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;-&lt;/span&gt;&lt;span style=&#34;color:#f5a97f&#34;&gt;13214&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;name&lt;/span&gt; = &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;some crazy string&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;_&lt;/span&gt; = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; await client.execute(uri: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;/user/&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;intToTest&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;/&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;name&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;, method: .&lt;span style=&#34;color:#c6a0f6&#34;&gt;get&lt;/span&gt;) { response &lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                #expect(response.status == .ok)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                #expect(&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;(buffer: response.body) == &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;found &lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;name&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt; for &lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;intToTest&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;codable--decodable&#34;&gt;Codable / Decodable&lt;/h3&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;MiniCodable&lt;/span&gt;:Decodable, ResponseEncodable {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;number&lt;/span&gt;: &lt;span style=&#34;color:#91d7e3&#34;&gt;Int&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;phrase&lt;/span&gt;: &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;?
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    @Test &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;testEncodable&lt;/span&gt;() async &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;app&lt;/span&gt; = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; await buildApplication(TestArguments())
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; await app.test(.router) { client &lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;_&lt;/span&gt; = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; await client.execute(uri: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;/encodable&amp;#34;&lt;/span&gt;, method: .&lt;span style=&#34;color:#c6a0f6&#34;&gt;get&lt;/span&gt;) { response &lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                #expect(response.status == .ok)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//print(String(buffer: response.body))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                #expect(&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;(buffer: response.body) == &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;{&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;number&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;:5,&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;phrase&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;hello!&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;}&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    @Test &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;testDecoding&lt;/span&gt;() async &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;app&lt;/span&gt; = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; await buildApplication(TestArguments())
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; await app.test(.router) { client &lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;_&lt;/span&gt; = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; await client.execute(uri: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;/decodable/default&amp;#34;&lt;/span&gt;, method: .post) { response &lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                #expect(response.status == .badRequest, &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;not the status expected from an empty post&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;codedData&lt;/span&gt; = MiniCodable(number: &lt;span style=&#34;color:#f5a97f&#34;&gt;34&lt;/span&gt;, phrase:&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;something to say&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;buffer&lt;/span&gt; = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; JSONEncoder().encodeAsByteBuffer(codedData, allocator: ByteBufferAllocator())
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// print(&amp;#34;coded: \(String(buffer:buffer))&amp;#34;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// var buffer = ByteBuffer(string: &amp;#34;{\&amp;#34;phrase\&amp;#34;:\&amp;#34;something to say\&amp;#34;,\&amp;#34;number\&amp;#34;:34}&amp;#34; )&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;_&lt;/span&gt; = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; await client.execute(uri: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;/decodable/default&amp;#34;&lt;/span&gt;, method: .post, body:buffer) { response &lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                #expect(response.status == .ok)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;responseBody default: &lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;(&lt;/span&gt;buffer: response.body&lt;span style=&#34;color:#a6da95&#34;&gt;))&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//json shows up in arbitrary order, so check for values individually.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;				&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//responseBody looks like&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;				&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//&amp;#34;DECODED: MiniCodable(number: 34, phrase: Optional(&amp;#34;something to say&amp;#34;))&amp;#34;).contains(&amp;#34;\&amp;#34;number\&amp;#34;:\(codedData.number)&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                #expect(&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;(buffer: response.body).&lt;span style=&#34;color:#91d7e3&#34;&gt;contains&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;number: &lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;codedData.number&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                #expect(&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;(buffer: response.body).&lt;span style=&#34;color:#91d7e3&#34;&gt;contains&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;phrase: &lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;Optional(&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;codedData.phrase!&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            buffer = ByteBuffer(string: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;number=&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;codedData.number&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;amp;phrase=&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;codedData.phrase!&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;_&lt;/span&gt; = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; await client.execute(uri: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;/decodable/form&amp;#34;&lt;/span&gt;, 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                                            method: .post, 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                                            &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//need header if detecting based on header, which not yet.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                                            &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//headers: [.contentType: &amp;#34;application/x-www-form-urlencoded&amp;#34;], &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                                            body:buffer) { response &lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                #expect(response.status == .ok)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;responseBody form: &lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;(&lt;/span&gt;buffer: response.body&lt;span style=&#34;color:#a6da95&#34;&gt;))&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                #expect(&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;(buffer: response.body).&lt;span style=&#34;color:#91d7e3&#34;&gt;contains&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;number: &lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;codedData.number&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                #expect(&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;(buffer: response.body).&lt;span style=&#34;color:#91d7e3&#34;&gt;contains&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;phrase: &lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;Optional(&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;codedData.phrase!&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;summary&#34;&gt;Summary&lt;/h2&gt;
&lt;p&gt;This post just barely scratches the surface of how to test a Hummingbird server. Also all the data being produced is fairly simple text or JSON&amp;hellip; what if I wanted to serve a NOT static HTML page? That&amp;rsquo;s next.&lt;/p&gt;
</description>
    </item>
    
    
    
    <item>
      <title>What kinda routes can I use with Hummingbird?</title>
      <link>https://whynotestflight.com/excuses/what-kinda-routes-can-i-use-with-hummingbird/</link>
      <pubDate>Sat, 13 Sep 2025 00:00:00 +0000</pubDate>
      
      <guid>https://whynotestflight.com/excuses/what-kinda-routes-can-i-use-with-hummingbird/</guid>
      <description>&lt;p&gt;I mean&amp;hellip;all of them? So this is all based on walking through the &lt;a href=&#34;https://docs.hummingbird.codes/2.0/documentation/hummingbird/routerguide&#34;&gt;Router Guide&lt;/a&gt;, but I wanted one project that served up the sampler.&lt;/p&gt;
&lt;p&gt;Here is a buildRouter function with a smorgasbord of examples.&lt;/p&gt;
&lt;p&gt;In context at: &lt;a href=&#34;https://github.com/carlynorama/HummingbirdExamples/tree/main/02_basic_responses&#34;&gt;https://github.com/carlynorama/HummingbirdExamples/tree/main/02_basic_responses&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&#34;buildrouter&#34;&gt;buildRouter&lt;/h2&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;buildRouter&lt;/span&gt;() -&amp;gt; Router&amp;lt;AppRequestContext&amp;gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;router&lt;/span&gt; = Router(context: AppRequestContext.&lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    router.addMiddleware {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// logging middleware&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        LogRequestsMiddleware(.info)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//serves the static files in public folder by default.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        FileMiddleware(searchForIndexHtml: &lt;span style=&#34;color:#f5a97f&#34;&gt;true&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// SIMPLE ROUTING&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// These three types have been given ResponseGenerator status by Hummingbird&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// - HTTPResponseStatus&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// - String&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// - Optional&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// The closure takes in a request and a context and returns&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// some ResponseGenerator&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    router.&lt;span style=&#34;color:#c6a0f6&#34;&gt;get&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;/ping&amp;#34;&lt;/span&gt;) { &lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt;, &lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; -&amp;gt; HTTPResponse.Status &lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; .ok
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    router.&lt;span style=&#34;color:#c6a0f6&#34;&gt;get&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;/hello&amp;#34;&lt;/span&gt;) { request, &lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; -&amp;gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Well Hello!&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\n\n&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;request&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// full call&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    router.on(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;/goodbye&amp;#34;&lt;/span&gt;, method: .&lt;span style=&#34;color:#c6a0f6&#34;&gt;get&lt;/span&gt;) { request, context &lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Ciao!&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//---- WILDCARDS&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// https://docs.hummingbird.codes/2.0/documentation/hummingbird/routerguide#Wildcards&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    router.&lt;span style=&#34;color:#c6a0f6&#34;&gt;get&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;/files/*&amp;#34;&lt;/span&gt;) { request, &lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; request.uri.description
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//note: ** is 1 or more, not zero or more. (2025/08)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    router.&lt;span style=&#34;color:#c6a0f6&#34;&gt;get&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;/doublewild/**&amp;#34;&lt;/span&gt;) { &lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt;, context &lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; context.parameters.getCatchAll().joined(separator: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;/&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//---- Parameter Capture&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// //https://docs.hummingbird.codes/2.0/documentation/hummingbird/routerguide#Parameter-Capture&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    router.&lt;span style=&#34;color:#c6a0f6&#34;&gt;get&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;/user/:id&amp;#34;&lt;/span&gt;) { &lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt;, context &lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;guard&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;id&lt;/span&gt; = context.parameters.&lt;span style=&#34;color:#c6a0f6&#34;&gt;get&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;id&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#c6a0f6&#34;&gt;as&lt;/span&gt;: &lt;span style=&#34;color:#91d7e3&#34;&gt;Int&lt;/span&gt;.&lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;) &lt;span style=&#34;color:#c6a0f6&#34;&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;throw&lt;/span&gt; HTTPError(.badRequest)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;id&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    router.&lt;span style=&#34;color:#c6a0f6&#34;&gt;get&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;/user/:id/:name&amp;#34;&lt;/span&gt;) { &lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt;, context &lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;guard&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;id&lt;/span&gt; = context.parameters.&lt;span style=&#34;color:#c6a0f6&#34;&gt;get&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;id&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#c6a0f6&#34;&gt;as&lt;/span&gt;: &lt;span style=&#34;color:#91d7e3&#34;&gt;Int&lt;/span&gt;.&lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;) &lt;span style=&#34;color:#c6a0f6&#34;&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;throw&lt;/span&gt; HTTPError(.badRequest)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;guard&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;name&lt;/span&gt; = context.parameters.&lt;span style=&#34;color:#c6a0f6&#34;&gt;get&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;name&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#c6a0f6&#34;&gt;as&lt;/span&gt;: &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;.&lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;) &lt;span style=&#34;color:#c6a0f6&#34;&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;throw&lt;/span&gt; HTTPError(.badRequest)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;found &lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;name&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt; for &lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;id&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    router.&lt;span style=&#34;color:#c6a0f6&#34;&gt;get&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;/img/{image}.jpg&amp;#34;&lt;/span&gt;) { &lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt;, context &lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;guard&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;imageName&lt;/span&gt; = context.parameters.&lt;span style=&#34;color:#c6a0f6&#34;&gt;get&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;image&amp;#34;&lt;/span&gt;) &lt;span style=&#34;color:#c6a0f6&#34;&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;throw&lt;/span&gt; HTTPError(.badRequest)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;switch&lt;/span&gt; imageName {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;case&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;bunny&amp;#34;&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34; &lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\\\n&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;  &lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\\&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt; /&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\\\n&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;  ( )&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\n&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;.( o ).&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//    \&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//     \ /\&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//     ( )&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//   .( o ).&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;default&lt;/span&gt;: &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;this is a &lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;imageName&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt; &amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    router.&lt;span style=&#34;color:#c6a0f6&#34;&gt;get&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;/query&amp;#34;&lt;/span&gt;) { request, &lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// extract parameter from URL of form /query?id={userId}&amp;amp;message={message}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;guard&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;id&lt;/span&gt; = request.uri.queryParameters.&lt;span style=&#34;color:#c6a0f6&#34;&gt;get&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;id&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#c6a0f6&#34;&gt;as&lt;/span&gt;: &lt;span style=&#34;color:#91d7e3&#34;&gt;Double&lt;/span&gt;.&lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;) &lt;span style=&#34;color:#c6a0f6&#34;&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;throw&lt;/span&gt; HTTPError(.badRequest, message: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;id?&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;guard&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;message&lt;/span&gt; = request.uri.queryParameters.&lt;span style=&#34;color:#c6a0f6&#34;&gt;get&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;message&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#c6a0f6&#34;&gt;as&lt;/span&gt;: &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;.&lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;) &lt;span style=&#34;color:#c6a0f6&#34;&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;throw&lt;/span&gt; HTTPError(.badRequest, message: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;message?&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;tell &lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;id&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt; I said &lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;message&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// GROUPS&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//if one has a logical group one can batch them together.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    router.group(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;/circus&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        .&lt;span style=&#34;color:#c6a0f6&#34;&gt;get&lt;/span&gt;(use: { &lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt;, &lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;if I had a list of circus acts I would show a list of circus acts&amp;#34;&lt;/span&gt; })
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        .&lt;span style=&#34;color:#c6a0f6&#34;&gt;get&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;peanuts&amp;#34;&lt;/span&gt;) { &lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt;, &lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;yummy peanuts&amp;#34;&lt;/span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        .group(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;clowns&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        .&lt;span style=&#34;color:#c6a0f6&#34;&gt;get&lt;/span&gt; { &lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt;, &lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;if I had a list of clowns I would show a list of clowns&amp;#34;&lt;/span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        .&lt;span style=&#34;color:#c6a0f6&#34;&gt;get&lt;/span&gt;(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;{id}&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            use: { &lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt;, context &lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;that&amp;#39;s the clown called &lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;context.parameters.&lt;span style=&#34;color:#c6a0f6&#34;&gt;get&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;id&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt; ?? &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;no ID&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;!&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            })
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;MiniCodable&lt;/span&gt;: Decodable, ResponseEncodable {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;number&lt;/span&gt;: &lt;span style=&#34;color:#91d7e3&#34;&gt;Int&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;phrase&lt;/span&gt;: &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;?
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//the default encoder is JSON&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    router.&lt;span style=&#34;color:#c6a0f6&#34;&gt;get&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;/encodable&amp;#34;&lt;/span&gt;) { &lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt;, &lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; -&amp;gt; MiniCodable &lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; MiniCodable(number: &lt;span style=&#34;color:#f5a97f&#34;&gt;5&lt;/span&gt;, phrase: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;hello!&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    router.group(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;/decodable&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        .&lt;span style=&#34;color:#c6a0f6&#34;&gt;get&lt;/span&gt; { &lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt;, &lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;this was a GET. Please submit some info using POST&amp;#34;&lt;/span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//curl -i -X POST localhost:8080/decodable/default -d&amp;#39;{&amp;#34;number&amp;#34;:12,&amp;#34;phrase&amp;#34;:&amp;#34;are you going to go my way&amp;#34;}&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        .post(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;default&amp;#34;&lt;/span&gt;) { request, context &lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;decoded&lt;/span&gt; = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; await request.decode(&lt;span style=&#34;color:#c6a0f6&#34;&gt;as&lt;/span&gt;: MiniCodable.&lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;, context: context)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;DECODED: &lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;decoded&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;DECODED: &lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;decoded&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;  &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//also consider an HTTPResponseStatus&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//curl -i -X POST &amp;#39;http://localhost:8080/decodable/form&amp;#39; -H &amp;#39;Content-Type: application/x-www-form-urlencoded&amp;#39; --data-raw &amp;#39;number=36&amp;amp;phrase=message%20string&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        .post(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;form&amp;#34;&lt;/span&gt;) { request, context &lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(request.headers)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;decoded&lt;/span&gt; = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; await URLEncodedFormDecoder().decode(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                MiniCodable.&lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;, from: request, context: context)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;DECODED: &lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;decoded&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;DECODED: &lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;decoded&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; router
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;testing-script&#34;&gt;Testing Script&lt;/h2&gt;
&lt;p&gt;To test them all here&amp;rsquo;s a build script with curl calls.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#!/bin/sh
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;MY_PORT&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;8080&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;separate &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;()&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;sleep 2s
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#91d7e3&#34;&gt;echo&lt;/span&gt; -e &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;\n---------------------\n&amp;#34;&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;curl -i &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;http://localhost:&lt;/span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;$MY_PORT&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;/ping&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;separate 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;curl -i &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;http://localhost:&lt;/span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;$MY_PORT&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;/hello&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;separate  
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;curl -i &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;http://localhost:&lt;/span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;$MY_PORT&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;/goodbye&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;separate 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;curl -i &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;http://localhost:&lt;/span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;$MY_PORT&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;/files/putonethingafter&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;separate 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;curl -i &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;http://localhost:&lt;/span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;$MY_PORT&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;/doublewild/put/anything/I/want&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;separate
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;curl -i &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;http://localhost:&lt;/span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;$MY_PORT&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;/user/8675309&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;separate
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;curl -i &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;http://localhost:&lt;/span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;$MY_PORT&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;/user/8675309/Jenny&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;separate
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;curl -i &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;http://localhost:&lt;/span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;$MY_PORT&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;/img/non-bunny.jpg&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;separate
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;curl -i &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;http://localhost:&lt;/span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;$MY_PORT&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;/img/bunny.jpg&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;separate
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;curl -i &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;http://localhost:&lt;/span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;$MY_PORT&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;/query?id=35.53&amp;amp;message=hello%20with%20spaces&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;separate
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;curl -i &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;http://localhost:&lt;/span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;$MY_PORT&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;/circus&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;separate
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;curl -i &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;http://localhost:&lt;/span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;$MY_PORT&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;/circus/peanuts&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;separate
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;curl -i &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;http://localhost:&lt;/span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;$MY_PORT&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;/circus/clowns&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;separate
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;curl -i &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;http://localhost:&lt;/span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;$MY_PORT&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;/circus/clowns/anythingcanbeanidforthis&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;separate 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;curl -i &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;http://localhost:&lt;/span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;$MY_PORT&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;/encodable&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;separate 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;curl -i -X POST localhost:&lt;span style=&#34;color:#f4dbd6&#34;&gt;$MY_PORT&lt;/span&gt;/decodable/default -d&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#39;{&amp;#34;number&amp;#34;:12,&amp;#34;phrase&amp;#34;:&amp;#34;are you going to go my way&amp;#34;}&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;separate 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;curl -i -X POST localhost:&lt;span style=&#34;color:#f4dbd6&#34;&gt;$MY_PORT&lt;/span&gt;/decodable/default -d&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#39;{&amp;#34;number&amp;#34;:14}&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;separate 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;curl -i -X POST &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#39;http://localhost:8080/decodable/form&amp;#39;&lt;/span&gt; -H &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#39;Content-Type: application/x-www-form-urlencoded&amp;#39;&lt;/span&gt; --data-raw &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#39;number=36&amp;amp;phrase=message%20string&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;separate 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;curl -i -X POST &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#39;http://localhost:8080/decodable/form&amp;#39;&lt;/span&gt; -H &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#39;Content-Type: application/x-www-form-urlencoded&amp;#39;&lt;/span&gt; --data-raw &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#39;number=36&amp;amp;phrase&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description>
    </item>
    
    
    
    <item>
      <title>How can I have Hummingbird serve static files?</title>
      <link>https://whynotestflight.com/excuses/how-can-i-have-hummingbird-serve-static-files/</link>
      <pubDate>Fri, 12 Sep 2025 00:00:00 +0000</pubDate>
      
      <guid>https://whynotestflight.com/excuses/how-can-i-have-hummingbird-serve-static-files/</guid>
      <description>&lt;p&gt;So I&amp;rsquo;ve already &lt;a href=&#34;https://whynotestflight.com/tags/hummingbird/&#34;&gt;mentioned Hummingbird&lt;/a&gt; a few times. Most recently I showed off the &lt;a href=&#34;https://github.com/carlynorama/HummingbirdExamples/tree/main/00_smallest_server&#34;&gt;&amp;ldquo;simplest server&amp;rdquo;&lt;/a&gt; in the &lt;a href=&#34;https://whynotestflight.com/excuses/how-do-i-cross-compile-a-swift-statically-linked-binary/&#34;&gt;how to deploy to an App server&lt;/a&gt; post. (It&amp;rsquo;s based of of the code &lt;a href=&#34;https://docs.hummingbird.codes/2.0/documentation/index/&#34;&gt;on the Hummingbird docs home&lt;/a&gt;.)&lt;/p&gt;
&lt;p&gt;This time I want to show how to set up &lt;a href=&#34;https://hummingbird.codes&#34;&gt;Hummingbird&lt;/a&gt; to host static pages. Hummingbird primarily focuses on serving Swift generated content, but static pages can be incredibly useful for testing APIs.&lt;/p&gt;
&lt;p&gt;This example started from a direct copy of &lt;a href=&#34;https://github.com/adam-fowler/swift-web&#34;&gt;https://github.com/adam-fowler/swift-web&lt;/a&gt; on 2025, Aug 15, and honestly did not change much.&lt;/p&gt;
&lt;p&gt;It&amp;rsquo;s a utility like &lt;code&gt;python3 -m http.server&lt;/code&gt; that will start a servlet based on the contents of a directory.  I&amp;rsquo;ll talk about the install later.&lt;/p&gt;
&lt;h2 id=&#34;the-code&#34;&gt;The Code&lt;/h2&gt;
&lt;p&gt;The code is all of 35 lines. It&amp;rsquo;s really simple.  It depends on Hummingbird and &lt;a href=&#34;https://apple.github.io/swift-argument-parser/documentation/argumentparser/&#34;&gt;ArgumentParser&lt;/a&gt; to make a 1 page app.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://docs.hummingbird.codes/2.0/documentation/hummingbird/filemiddleware&#34;&gt;FileMiddleware&lt;/a&gt; is provided by Hummingbird, but it&amp;rsquo;s possible to write custom versions. &lt;a href=&#34;https://en.wikipedia.org/wiki/Middleware&#34;&gt;Middleware&lt;/a&gt; in this context is kind of like a plugin that a web app developer can insert between the request and the response, altering Hummingbird&amp;rsquo;s default behaviors.  Normally if a route isn&amp;rsquo;t cataloged in the &lt;a href=&#34;https://docs.hummingbird.codes/2.0/documentation/hummingbird/routerguide&#34;&gt;Router&lt;/a&gt;, Hummingbird would send a &lt;a href=&#34;https://en.wikipedia.org/wiki/HTTP_404&#34;&gt;404 Response&lt;/a&gt;.  With &lt;code&gt;FileMiddleware&lt;/code&gt; registered, instead Hummingbird will look in the specified directory for a path that matches the route first.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-Swift&#34; data-lang=&#34;Swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;ArgumentParser&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;Hummingbird&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;Logging&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;@main
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;WebServer&lt;/span&gt;: AsyncParsableCommand {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    @Option(name: .shortAndLong)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//will cause issue in containers but this is for&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//running locally.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;hostname&lt;/span&gt;: &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt; = &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;127.0.0.1&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    @Option(name: .shortAndLong)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;port&lt;/span&gt;: &lt;span style=&#34;color:#91d7e3&#34;&gt;Int&lt;/span&gt; = &lt;span style=&#34;color:#f5a97f&#34;&gt;8080&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    @Argument
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;folder&lt;/span&gt;: &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt; = &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;.&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;run&lt;/span&gt;() async &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(folder)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;logger&lt;/span&gt; = Logger(label: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;swift-serve&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;router&lt;/span&gt; = Router()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        router.middlewares.add(FileMiddleware(&lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;.folder, searchForIndexHtml: &lt;span style=&#34;color:#f5a97f&#34;&gt;true&lt;/span&gt;, logger: logger))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        router.middlewares.add(LogRequestsMiddleware(.info))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;app&lt;/span&gt; = Application(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            router: router,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            configuration: .&lt;span style=&#34;color:#ed8796&#34;&gt;init&lt;/span&gt;(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                address: .hostname(&lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;.hostname, port: &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;.port),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                serverName: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;swift-serve&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            ),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            logger: logger
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        )
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; await app.runService()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The Package.swift&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-Swift&#34; data-lang=&#34;Swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// swift-tools-version:6.1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;PackageDescription&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;package&lt;/span&gt; = Package(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    name: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;swift-serve&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    platforms : [.macOS(.v14)],
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    products: [.executable(name: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;swift-serve&amp;#34;&lt;/span&gt;, targets: [&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;swift-serve&amp;#34;&lt;/span&gt;])],
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    dependencies: [
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        .package(url: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;https://github.com/hummingbird-project/hummingbird.git&amp;#34;&lt;/span&gt;, from: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;2.0.0&amp;#34;&lt;/span&gt;),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        .package(url: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;https://github.com/apple/swift-argument-parser.git&amp;#34;&lt;/span&gt;, from: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;1.3.0&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    ],
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    targets: [
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        .executableTarget(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            name: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;swift-serve&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            dependencies: [
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                .product(name: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;ArgumentParser&amp;#34;&lt;/span&gt;, package: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;swift-argument-parser&amp;#34;&lt;/span&gt;),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                .product(name: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Hummingbird&amp;#34;&lt;/span&gt;, package: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;hummingbird&amp;#34;&lt;/span&gt;),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            ]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        ),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    ]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;usage&#34;&gt;Usage&lt;/h2&gt;
&lt;p&gt;If one goes to the example&amp;rsquo;s repo, there&amp;rsquo;s &lt;a href=&#34;https://github.com/carlynorama/HummingbirdExamples/tree/main/01_swift-serve/public&#34;&gt;a folder called &amp;ldquo;public&amp;rdquo; there&lt;/a&gt; with some HTML for testing. The lines&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-Swift&#34; data-lang=&#34;Swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    @Argument
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;folder&lt;/span&gt;: &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt; = &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;.&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;mean that the server will treat the present working directory as the root folder if nothing else gets specified. The &lt;code&gt;FileMiddleware&lt;/code&gt; will actually look for a folder called &lt;code&gt;public&lt;/code&gt; in the package root if nothing is specified, but in this example I put the demo directory right outside the root to give an excuse to show passing a path.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-shell&#34; data-lang=&#34;shell&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# from the directory with the README / &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#91d7e3&#34;&gt;cd&lt;/span&gt; swift-serve
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;swift run swift-serve ../public
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;installing-the-tool&#34;&gt;Installing the Tool&lt;/h2&gt;
&lt;p&gt;It&amp;rsquo;d hardly be convenient to keep recompiling or go digging in a build folder whenever it&amp;rsquo;s time to run a server.&lt;/p&gt;
&lt;p&gt;Fowler provides instruction on how to install the server tool using &lt;a href=&#34;https://github.com/yonaskolb/Mint&#34;&gt;mint&lt;/a&gt;.  It handles where to put and where to find all the compiled binaries really nicely.&lt;/p&gt;
&lt;p&gt;But for fun, let&amp;rsquo;s go through the exercise of installing the hand written debug version of the code in a folder called &lt;code&gt;~/mybin&lt;/code&gt; (Although one could certainly make a release version first: &lt;code&gt;swift build --configuration release&lt;/code&gt;). I prefer to do this with tools I&amp;rsquo;ve written, rather than putting them in &lt;code&gt;/usr/local/bin&lt;/code&gt; or &lt;code&gt;/usr/bin&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;First step, copy the executable. A symlink would also be an option if you wanted it to stay up to date as you developed. (&lt;code&gt;ln -s /path/to/original /path/to/link&lt;/code&gt;)&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-shell&#34; data-lang=&#34;shell&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## make the folder&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;mkdir ~/mybin
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## From Directory with this readme, after having run `swift build` at the very least. &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#91d7e3&#34;&gt;cd&lt;/span&gt; swift-serve/.build/debug
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;cp swift-serve ~/mybin/swift-serve
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#91d7e3&#34;&gt;cd&lt;/span&gt; -
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#91d7e3&#34;&gt;cd&lt;/span&gt; public
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;~/mybin/swift-serve
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This should run the server.  If you&amp;rsquo;d like to add the ~/mybin to the &lt;a href=&#34;https://en.wikipedia.org/wiki/PATH_(variable)&#34;&gt;path&lt;/a&gt;&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-zsh&#34; data-lang=&#34;zsh&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# see all the folders in your path&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#91d7e3&#34;&gt;echo&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;$PATH&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## then either add it to the beginning to search it first&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;PATH&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt;~/mybin:&lt;span style=&#34;color:#f4dbd6&#34;&gt;$PATH&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## OR add it to the end to search it last. &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;PATH&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;$PATH&lt;/span&gt;:~/mybin
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## check your path again&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#91d7e3&#34;&gt;echo&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;$PATH&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This will ONLY work for THIS shell. To update your profile try seeing what you currently have, e.g. &lt;code&gt;cat ~/.zprofile&lt;/code&gt; if using zsh or &lt;code&gt;ls -al ~/&lt;/code&gt; to go hunting.&lt;/p&gt;
&lt;p&gt;Add something like&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;[[&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;:&lt;/span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;$PATH&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;:&amp;#34;&lt;/span&gt; !&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; *&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;:~/mybin:&amp;#34;&lt;/span&gt;* &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;]]&lt;/span&gt;; &lt;span style=&#34;color:#c6a0f6&#34;&gt;then&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#91d7e3&#34;&gt;export&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;PATH&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Users/&lt;/span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;$USER&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;/mybin:&lt;/span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;$PATH&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;fi&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;at the bottom of the file to add your custom folder at the front of the PATH&amp;rsquo;s line every time you open a shell controlled by that profile.&lt;/p&gt;
&lt;p&gt;CAUTION: This means programs in &lt;code&gt;~/mybin&lt;/code&gt; always win. If you name your program the same as something else important, that&amp;rsquo;ll be some serious woe.&lt;/p&gt;
&lt;p&gt;Open a new terminal window (or &lt;code&gt;hash -r&lt;/code&gt; the current one) and&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#91d7e3&#34;&gt;cd&lt;/span&gt; public
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;swift-serve
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;should work now!&lt;/p&gt;
</description>
    </item>
    
    
    
    <item>
      <title>Can I animate color changes over time with CSS?</title>
      <link>https://whynotestflight.com/excuses/can-i-animate-color-changes-over-time-with-css/</link>
      <pubDate>Thu, 11 Sep 2025 00:00:00 +0000</pubDate>
      
      <guid>https://whynotestflight.com/excuses/can-i-animate-color-changes-over-time-with-css/</guid>
      <description>&lt;p&gt;So, can color be animated with CSS? Yes. What way will work best for my purposes, TBD.&lt;/p&gt;
&lt;h2 id=&#34;hello-animation&#34;&gt;Hello Animation&lt;/h2&gt;
&lt;p&gt;Here&amp;rsquo;s a variation of &lt;a href=&#34;https://developer.mozilla.org/en-US/docs/Web/CSS/animation#animating_multiple_properties&#34;&gt;an example from mdn&amp;rsquo;s &lt;code&gt;animation&lt;/code&gt; page&lt;/a&gt;&lt;/p&gt;
&lt;style&gt;
    #example1 {
      width: 50vw;
      height: 50vh;
      overflow: hidden;
      background-color: lightblue;
      display: flex;
      justify-content: center;
      align: center;
    }

    #example1 .sun {
        background-color: yellow;
        border-radius: 50%;
        /* creates a circular background */
        height: 20vh;
        /* makes the sun the size of the viewport */
        aspect-ratio: 1 / 1;
        animation: 4s linear 0s infinite alternate animating-multiple-properties;
    }

    @keyframes animating-multiple-properties {
      from {
          transform: translateY(calc(50vh - 20vh));
          background-color: red;
          filter: brightness(75%);
      }

      to {
          transform: translateY(0%);
          background-color: orange;
          /* unset properties i.e. &#39;filter&#39; will revert to default values */
      }
    }
&lt;/style&gt;
&lt;div id=&#34;example1&#34;&gt;
  &lt;div class=&#34;sun&#34;&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-HTML&#34; data-lang=&#34;HTML&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;style&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    #&lt;span style=&#34;color:#f5a97f&#34;&gt;example1&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#c6a0f6&#34;&gt;width&lt;/span&gt;: &lt;span style=&#34;color:#f5a97f&#34;&gt;50&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;vw&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#c6a0f6&#34;&gt;height&lt;/span&gt;: &lt;span style=&#34;color:#f5a97f&#34;&gt;50&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;vh&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#c6a0f6&#34;&gt;overflow&lt;/span&gt;: &lt;span style=&#34;color:#f5a97f&#34;&gt;hidden&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#c6a0f6&#34;&gt;background-color&lt;/span&gt;: &lt;span style=&#34;color:#f5a97f&#34;&gt;lightblue&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#c6a0f6&#34;&gt;display&lt;/span&gt;: &lt;span style=&#34;color:#f5a97f&#34;&gt;flex&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#c6a0f6&#34;&gt;justify-content&lt;/span&gt;: &lt;span style=&#34;color:#f5a97f&#34;&gt;center&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      align: &lt;span style=&#34;color:#f5a97f&#34;&gt;center&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;     
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    #&lt;span style=&#34;color:#f5a97f&#34;&gt;example1&lt;/span&gt; .&lt;span style=&#34;color:#eed49f&#34;&gt;sun&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#c6a0f6&#34;&gt;background-color&lt;/span&gt;: &lt;span style=&#34;color:#f5a97f&#34;&gt;yellow&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#c6a0f6&#34;&gt;border-radius&lt;/span&gt;: &lt;span style=&#34;color:#f5a97f&#34;&gt;50&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;%&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;/* creates a circular background */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#c6a0f6&#34;&gt;height&lt;/span&gt;: &lt;span style=&#34;color:#f5a97f&#34;&gt;20&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;vh&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;/* makes the sun the size of the viewport */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#c6a0f6&#34;&gt;aspect-ratio&lt;/span&gt;: &lt;span style=&#34;color:#f5a97f&#34;&gt;1&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;/&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;1&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#c6a0f6&#34;&gt;animation&lt;/span&gt;: &lt;span style=&#34;color:#f5a97f&#34;&gt;4&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;s&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;linear&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;0&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;s&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;infinite&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;alternate&lt;/span&gt; animating-multiple-properties;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    @&lt;span style=&#34;color:#c6a0f6&#34;&gt;keyframes&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;animating-multiple-properties&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#c6a0f6&#34;&gt;from&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#c6a0f6&#34;&gt;transform&lt;/span&gt;: &lt;span style=&#34;color:#91d7e3&#34;&gt;translateY&lt;/span&gt;(&lt;span style=&#34;color:#91d7e3&#34;&gt;calc&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;50&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;vh&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;-&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;20&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;vh&lt;/span&gt;));
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#c6a0f6&#34;&gt;background-color&lt;/span&gt;: &lt;span style=&#34;color:#f5a97f&#34;&gt;red&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#c6a0f6&#34;&gt;filter&lt;/span&gt;: &lt;span style=&#34;color:#91d7e3&#34;&gt;brightness&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;75&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;%&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#c6a0f6&#34;&gt;to&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#c6a0f6&#34;&gt;transform&lt;/span&gt;: &lt;span style=&#34;color:#91d7e3&#34;&gt;translateY&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;0&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;%&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#c6a0f6&#34;&gt;background-color&lt;/span&gt;: &lt;span style=&#34;color:#f5a97f&#34;&gt;orange&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;/* unset properties i.e. &amp;#39;filter&amp;#39; will revert to default values */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;/&lt;span style=&#34;color:#c6a0f6&#34;&gt;style&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;div&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;id&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;example1&amp;#34;&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &amp;lt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;div&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;class&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;sun&amp;#34;&lt;/span&gt;&amp;gt;&amp;lt;/&lt;span style=&#34;color:#c6a0f6&#34;&gt;div&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;div&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;with-variables&#34;&gt;With Variables&lt;/h2&gt;
&lt;p&gt;CSS has variables! This animation is just the color change from the first, but done with variables.&lt;/p&gt;
&lt;style&gt;
  :root {
     --example2-start-color: red;
     --example2-end-color: orange;
  }
  #example2 {  
    width: 50vw;
    height: 50vh;
    overflow: hidden;
    background-color: lightblue;
    display: flex;
    justify-content: center;
    align-items: center;
  }

  #example2 .sun {
      background-color: yellow;
      border-radius: 50%;
      height: 30vh;
      aspect-ratio: 1 / 1;
      animation: 10s linear 0s infinite alternate example-two-frames;
  }

  @keyframes example-two-frames {
    from {
        background-color: var(--example2-start-color);
        filter: brightness(75%);
    }
    to {
        background-color: var(--example2-end-color);
    }
  }
&lt;/style&gt;
&lt;div id=&#34;example2&#34;&gt;
  &lt;div class=&#34;sun&#34;&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-HTML&#34; data-lang=&#34;HTML&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;style&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  :&lt;span style=&#34;color:#8aadf4;font-weight:bold&#34;&gt;root&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;     &lt;span style=&#34;color:#f4dbd6&#34;&gt;--example2-start-color&lt;/span&gt;: &lt;span style=&#34;color:#f5a97f&#34;&gt;red&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;     &lt;span style=&#34;color:#f4dbd6&#34;&gt;--example2-end-color&lt;/span&gt;: &lt;span style=&#34;color:#f5a97f&#34;&gt;orange&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  #&lt;span style=&#34;color:#f5a97f&#34;&gt;example2&lt;/span&gt; {  
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;width&lt;/span&gt;: &lt;span style=&#34;color:#f5a97f&#34;&gt;50&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;vw&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;height&lt;/span&gt;: &lt;span style=&#34;color:#f5a97f&#34;&gt;50&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;vh&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;overflow&lt;/span&gt;: &lt;span style=&#34;color:#f5a97f&#34;&gt;hidden&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;background-color&lt;/span&gt;: &lt;span style=&#34;color:#f5a97f&#34;&gt;lightblue&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;display&lt;/span&gt;: &lt;span style=&#34;color:#f5a97f&#34;&gt;flex&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;justify-content&lt;/span&gt;: &lt;span style=&#34;color:#f5a97f&#34;&gt;center&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;align-items&lt;/span&gt;: &lt;span style=&#34;color:#f5a97f&#34;&gt;center&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  #&lt;span style=&#34;color:#f5a97f&#34;&gt;example2&lt;/span&gt; .&lt;span style=&#34;color:#eed49f&#34;&gt;sun&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#c6a0f6&#34;&gt;background-color&lt;/span&gt;: &lt;span style=&#34;color:#f5a97f&#34;&gt;yellow&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#c6a0f6&#34;&gt;border-radius&lt;/span&gt;: &lt;span style=&#34;color:#f5a97f&#34;&gt;50&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;%&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#c6a0f6&#34;&gt;height&lt;/span&gt;: &lt;span style=&#34;color:#f5a97f&#34;&gt;30&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;vh&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#c6a0f6&#34;&gt;aspect-ratio&lt;/span&gt;: &lt;span style=&#34;color:#f5a97f&#34;&gt;1&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;/&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;1&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#c6a0f6&#34;&gt;animation&lt;/span&gt;: &lt;span style=&#34;color:#f5a97f&#34;&gt;10&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;s&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;linear&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;0&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;s&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;infinite&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;alternate&lt;/span&gt; example-two-frames;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  @&lt;span style=&#34;color:#c6a0f6&#34;&gt;keyframes&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;example-two-frames&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;from&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;background-color&lt;/span&gt;: &lt;span style=&#34;color:#8aadf4&#34;&gt;var&lt;/span&gt;(&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;--&lt;/span&gt;example2&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;-&lt;/span&gt;&lt;span style=&#34;color:#f5a97f&#34;&gt;start&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;-&lt;/span&gt;&lt;span style=&#34;color:#f5a97f&#34;&gt;color&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;filter&lt;/span&gt;: &lt;span style=&#34;color:#91d7e3&#34;&gt;brightness&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;75&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;%&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;to&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;background-color&lt;/span&gt;: &lt;span style=&#34;color:#8aadf4&#34;&gt;var&lt;/span&gt;(&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;--&lt;/span&gt;example2&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;-&lt;/span&gt;&lt;span style=&#34;color:#f5a97f&#34;&gt;end&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;-&lt;/span&gt;&lt;span style=&#34;color:#f5a97f&#34;&gt;color&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;/&lt;span style=&#34;color:#c6a0f6&#34;&gt;style&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;div&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;id&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;example2&amp;#34;&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &amp;lt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;div&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;class&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;sun&amp;#34;&lt;/span&gt;&amp;gt;&amp;lt;/&lt;span style=&#34;color:#c6a0f6&#34;&gt;div&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;/&lt;span style=&#34;color:#c6a0f6&#34;&gt;div&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;control-a-variable-with-javascript&#34;&gt;Control a Variable With Javascript&lt;/h2&gt;
&lt;p&gt;Once you have a variable, it can be controlled via JavaScript. This sun should be skittering through hue changes.&lt;/p&gt;
&lt;p&gt;NOTE: Some blog meta. All the &lt;code&gt;&amp;lt;script&amp;gt;&lt;/code&gt; tag enclosed code from the post is consolidated into one script tag at the bottom of the post.&lt;/p&gt;
&lt;style&gt;
  :root {
     --example3-color: red;
  }
  #example3 {  
    width: 50vw;
    height: 50vh;
    overflow: hidden;
    background-color: lightblue;
    display: flex;
    justify-content: center;
    align-items: center;
  }

  #example3 .sun {
    background-color: yellow;
    border-radius: 50%;
    height: 30vh;
    aspect-ratio: 1 / 1;
    background: var(--example3-color);
  }
&lt;/style&gt;
&lt;div id=&#34;example3&#34;&gt;
  &lt;div class=&#34;sun&#34;&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-HTML&#34; data-lang=&#34;HTML&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;style&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  :&lt;span style=&#34;color:#8aadf4;font-weight:bold&#34;&gt;root&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;     &lt;span style=&#34;color:#f4dbd6&#34;&gt;--example3-color&lt;/span&gt;: &lt;span style=&#34;color:#f5a97f&#34;&gt;red&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  #&lt;span style=&#34;color:#f5a97f&#34;&gt;example3&lt;/span&gt; {  
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;width&lt;/span&gt;: &lt;span style=&#34;color:#f5a97f&#34;&gt;50&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;vw&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;height&lt;/span&gt;: &lt;span style=&#34;color:#f5a97f&#34;&gt;50&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;vh&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;overflow&lt;/span&gt;: &lt;span style=&#34;color:#f5a97f&#34;&gt;hidden&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;background-color&lt;/span&gt;: &lt;span style=&#34;color:#f5a97f&#34;&gt;lightblue&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;display&lt;/span&gt;: &lt;span style=&#34;color:#f5a97f&#34;&gt;flex&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;justify-content&lt;/span&gt;: &lt;span style=&#34;color:#f5a97f&#34;&gt;center&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;align-items&lt;/span&gt;: &lt;span style=&#34;color:#f5a97f&#34;&gt;center&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  #&lt;span style=&#34;color:#f5a97f&#34;&gt;example3&lt;/span&gt; .&lt;span style=&#34;color:#eed49f&#34;&gt;sun&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;background-color&lt;/span&gt;: &lt;span style=&#34;color:#f5a97f&#34;&gt;yellow&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;border-radius&lt;/span&gt;: &lt;span style=&#34;color:#f5a97f&#34;&gt;50&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;%&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;height&lt;/span&gt;: &lt;span style=&#34;color:#f5a97f&#34;&gt;30&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;vh&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;aspect-ratio&lt;/span&gt;: &lt;span style=&#34;color:#f5a97f&#34;&gt;1&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;/&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;1&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;background&lt;/span&gt;: &lt;span style=&#34;color:#8aadf4&#34;&gt;var&lt;/span&gt;(&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;--&lt;/span&gt;example3&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;-&lt;/span&gt;&lt;span style=&#34;color:#f5a97f&#34;&gt;color&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;/&lt;span style=&#34;color:#c6a0f6&#34;&gt;style&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;div&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;id&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;example3&amp;#34;&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &amp;lt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;div&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;class&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;sun&amp;#34;&lt;/span&gt;&amp;gt;&amp;lt;/&lt;span style=&#34;color:#c6a0f6&#34;&gt;div&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;/&lt;span style=&#34;color:#c6a0f6&#34;&gt;div&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;script&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; startTime &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;null&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; hue &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; root &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;document&lt;/span&gt;.documentElement;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;function&lt;/span&gt; animateColor(currentTime) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; (&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;!&lt;/span&gt;startTime) startTime &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; currentTime;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#c6a0f6&#34;&gt;const&lt;/span&gt; elapsed &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; currentTime &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;-&lt;/span&gt; startTime;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  hue &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; elapsed&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;/&lt;/span&gt;&lt;span style=&#34;color:#f5a97f&#34;&gt;60&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  root.style.setProperty(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#39;--example3-color&amp;#39;&lt;/span&gt;, &lt;span style=&#34;color:#a6da95&#34;&gt;`hsl(&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;${&lt;/span&gt;hue&lt;span style=&#34;color:#a6da95&#34;&gt;}&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;, 100%, 50%)`&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//console.log(&amp;#34;hello animateColor.&amp;#34;)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;  requestAnimationFrame(animateColor);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#91d7e3&#34;&gt;window&lt;/span&gt;.onload &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;function&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    animateColor(&lt;span style=&#34;color:#c6a0f6&#34;&gt;new&lt;/span&gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;Date&lt;/span&gt;())
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//console.log(&amp;#34;hello from the script.&amp;#34;)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;  }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;/&lt;span style=&#34;color:#c6a0f6&#34;&gt;script&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;animation-delays&#34;&gt;Animation Delays&lt;/h2&gt;
&lt;p&gt;It&amp;rsquo;s possible to delay an animation&amp;rsquo;s start time with &lt;a href=&#34;https://developer.mozilla.org/en-US/docs/Web/CSS/animation-delay&#34;&gt;&lt;code&gt;animation-delay&lt;/code&gt;&lt;/a&gt;. Negative numbers work too! It jumps the position of the animation further in as if the animation had been playing for that long before the page had loaded.&lt;/p&gt;
&lt;p&gt;This sun should track with the seconds, popping back to red at the flip to a new minute, no matter the precise time the page was opened.&lt;/p&gt;
&lt;style&gt;
  :root {
    --example4-start-color: red;
    --example4-end-color: yellow;
    --example4-delay: 0s;
  }
  #example4 {  
    width: 50vw;
    height: 50vh;
    overflow: hidden;
    background-color: lightblue;
    display: flex;
    justify-content: center;
    align-items: center;
  }
  #example4 .sun {
    border-radius: 50%;
    height: 30vh;
    aspect-ratio: 1 / 1;
    background: var(--example4-start-color);
    animation: example-four-frames 60s none var(--example4-delay) infinite;
  }
  @keyframes example-four-frames {
    from {
        background-color: var(--example4-start-color);
        filter: brightness(75%);
    }
    to {
        background-color: var(--example4-end-color);
    }
  }
&lt;/style&gt;
&lt;div id=&#34;example4&#34;&gt;
  &lt;div class=&#34;sun&#34;&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-HTML&#34; data-lang=&#34;HTML&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;style&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  :&lt;span style=&#34;color:#8aadf4;font-weight:bold&#34;&gt;root&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f4dbd6&#34;&gt;--example4-start-color&lt;/span&gt;: &lt;span style=&#34;color:#f5a97f&#34;&gt;red&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f4dbd6&#34;&gt;--example4-end-color&lt;/span&gt;: &lt;span style=&#34;color:#f5a97f&#34;&gt;yellow&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f4dbd6&#34;&gt;--example4-delay&lt;/span&gt;: &lt;span style=&#34;color:#f5a97f&#34;&gt;0&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;s&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  #&lt;span style=&#34;color:#f5a97f&#34;&gt;example4&lt;/span&gt; {  
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;width&lt;/span&gt;: &lt;span style=&#34;color:#f5a97f&#34;&gt;50&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;vw&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;height&lt;/span&gt;: &lt;span style=&#34;color:#f5a97f&#34;&gt;50&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;vh&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;overflow&lt;/span&gt;: &lt;span style=&#34;color:#f5a97f&#34;&gt;hidden&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;background-color&lt;/span&gt;: &lt;span style=&#34;color:#f5a97f&#34;&gt;lightblue&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;display&lt;/span&gt;: &lt;span style=&#34;color:#f5a97f&#34;&gt;flex&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;justify-content&lt;/span&gt;: &lt;span style=&#34;color:#f5a97f&#34;&gt;center&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;align-items&lt;/span&gt;: &lt;span style=&#34;color:#f5a97f&#34;&gt;center&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  #&lt;span style=&#34;color:#f5a97f&#34;&gt;example4&lt;/span&gt; .&lt;span style=&#34;color:#eed49f&#34;&gt;sun&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;border-radius&lt;/span&gt;: &lt;span style=&#34;color:#f5a97f&#34;&gt;50&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;%&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;/* creates a circular background */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;height&lt;/span&gt;: &lt;span style=&#34;color:#f5a97f&#34;&gt;30&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;vh&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;/* makes the sun the size of the viewport */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;aspect-ratio&lt;/span&gt;: &lt;span style=&#34;color:#f5a97f&#34;&gt;1&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;/&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;1&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;background&lt;/span&gt;: &lt;span style=&#34;color:#8aadf4&#34;&gt;var&lt;/span&gt;(&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;--&lt;/span&gt;example4&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;-&lt;/span&gt;&lt;span style=&#34;color:#f5a97f&#34;&gt;start&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;-&lt;/span&gt;&lt;span style=&#34;color:#f5a97f&#34;&gt;color&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;animation&lt;/span&gt;: example-four-frames &lt;span style=&#34;color:#f5a97f&#34;&gt;60&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;s&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;none&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;var&lt;/span&gt;(&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;--&lt;/span&gt;example4&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;-&lt;/span&gt;delay) &lt;span style=&#34;color:#f5a97f&#34;&gt;infinite&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  @&lt;span style=&#34;color:#c6a0f6&#34;&gt;keyframes&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;example-four-frames&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;from&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;background-color&lt;/span&gt;: &lt;span style=&#34;color:#8aadf4&#34;&gt;var&lt;/span&gt;(&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;--&lt;/span&gt;example4&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;-&lt;/span&gt;&lt;span style=&#34;color:#f5a97f&#34;&gt;start&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;-&lt;/span&gt;&lt;span style=&#34;color:#f5a97f&#34;&gt;color&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;filter&lt;/span&gt;: &lt;span style=&#34;color:#91d7e3&#34;&gt;brightness&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;75&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;%&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;to&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;background-color&lt;/span&gt;: &lt;span style=&#34;color:#8aadf4&#34;&gt;var&lt;/span&gt;(&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;--&lt;/span&gt;example4&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;-&lt;/span&gt;&lt;span style=&#34;color:#f5a97f&#34;&gt;end&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;-&lt;/span&gt;&lt;span style=&#34;color:#f5a97f&#34;&gt;color&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;/&lt;span style=&#34;color:#c6a0f6&#34;&gt;style&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;div&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;id&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;example4&amp;#34;&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &amp;lt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;div&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;class&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;sun&amp;#34;&lt;/span&gt;&amp;gt;&amp;lt;/&lt;span style=&#34;color:#c6a0f6&#34;&gt;div&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;/&lt;span style=&#34;color:#c6a0f6&#34;&gt;div&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;script&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;function&lt;/span&gt; setDelay() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; date &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;new&lt;/span&gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;Date&lt;/span&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; seconds &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; date.getSeconds();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; root &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;document&lt;/span&gt;.documentElement;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; delay &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; seconds &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;*&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;-&lt;/span&gt;&lt;span style=&#34;color:#f5a97f&#34;&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    console.log(seconds, delay);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    console.log(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;hello from setDelay&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    root.style.setProperty(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#39;--example4-delay&amp;#39;&lt;/span&gt;, &lt;span style=&#34;color:#a6da95&#34;&gt;`&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;${&lt;/span&gt;delay&lt;span style=&#34;color:#a6da95&#34;&gt;}&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;s`&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#91d7e3&#34;&gt;window&lt;/span&gt;.onload &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;function&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    setDelay();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;/&lt;span style=&#34;color:#c6a0f6&#34;&gt;script&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;resources&#34;&gt;Resources&lt;/h2&gt;
&lt;p&gt;I bought &lt;a href=&#34;https://www.udemy.com/course/css-the-complete-guide-incl-flexbox-grid-sass/&#34;&gt;a Udemy course on CSS&lt;/a&gt; a while ago now that I keep going back to when i need a CSS refresh.&lt;/p&gt;
&lt;p&gt;But here are some of the links that helped in making the examples for this post:&lt;/p&gt;
&lt;h3 id=&#34;general-css-tools&#34;&gt;General CSS Tools&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://easings.net&#34;&gt;https://easings.net&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://caniuse.com&#34;&gt;https://caniuse.com&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://shouldiprefix.com&#34;&gt;https://shouldiprefix.com&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://css-tricks.com/autoprefixer/&#34;&gt;https://css-tricks.com/autoprefixer/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://html5please.com&#34;&gt;https://html5please.com&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;animation-docs&#34;&gt;Animation Docs&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://www.w3.org/TR/2025/NOTE-css-2025-20250909/&#34;&gt;https://www.w3.org/TR/2025/NOTE-css-2025-20250909/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://www.w3.org/TR/css-transforms/&#34;&gt;https://www.w3.org/TR/css-transforms/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://www.w3.org/TR/css-transitions/&#34;&gt;https://www.w3.org/TR/css-transitions/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://www.w3.org/TR/css-animations/&#34;&gt;https://www.w3.org/TR/css-animations/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_animations/Using_CSS_animations&#34;&gt;https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_animations/Using_CSS_animations&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_transitions/Using_CSS_transitions&#34;&gt;https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_transitions/Using_CSS_transitions&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_transforms/Using_CSS_transforms&#34;&gt;https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_transforms/Using_CSS_transforms&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://developer.mozilla.org/en-US/docs/Web/CSS/animation&#34;&gt;https://developer.mozilla.org/en-US/docs/Web/CSS/animation&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;clocks-and-timers&#34;&gt;Clocks and Timers&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://www.javascripttutorial.net/javascript-dom/javascript-countdown-timer/&#34;&gt;https://www.javascripttutorial.net/javascript-dom/javascript-countdown-timer/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://www.w3schools.com/howto/howto_js_countdown.asp&#34;&gt;https://www.w3schools.com/howto/howto_js_countdown.asp&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;easy time display: &lt;a href=&#34;https://stackoverflow.com/a/39528161&#34;&gt;https://stackoverflow.com/a/39528161&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;requestAnimationFrame vs setTimeout: &lt;a href=&#34;https://stackoverflow.com/a/38709924&#34;&gt;https://stackoverflow.com/a/38709924&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://dev.to/moyedx3/10-settimeout-setinterval-and-requestanimationframe-1io4&#34;&gt;https://dev.to/moyedx3/10-settimeout-setinterval-and-requestanimationframe-1io4&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;updating-variables&#34;&gt;Updating Variables&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://css-tricks.com/updating-a-css-variable-with-javascript/&#34;&gt;https://css-tricks.com/updating-a-css-variable-with-javascript/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;just-was-fun&#34;&gt;Just was Fun&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://css-tricks.com/css-animation-tricks/&#34;&gt;https://css-tricks.com/css-animation-tricks/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;script&gt;
let startTime = null;
let hue = 0
function animateColor(currentTime) {
  let root = document.documentElement;
  if (!startTime) startTime = currentTime;
  const elapsed = currentTime - startTime;
  hue = elapsed/60;
  root.style.setProperty(&#39;--example3-color&#39;, `hsl(${hue}, 100%, 50%)`)
  // console.log(&#34;hello animateColor.&#34;)
  requestAnimationFrame(animateColor);
}
function setDelay() {
    var date = new Date();
    var seconds = date.getSeconds();
    let root = document.documentElement;
    let delay = seconds * -1
    console.log(seconds, delay);
    console.log(&#34;hello from setDelay&#34;)
    root.style.setProperty(&#39;--example4-delay&#39;, `${delay}s`);
}
  window.onload = function() {
    setDelay();
        animateColor(new Date())
    console.log(&#34;hello from the script.&#34;)
  }
&lt;/script&gt;</description>
    </item>
    
    
    
    <item>
      <title>Can I make a Swift-wrapped HTTP GET request from the ESP32C6?</title>
      <link>https://whynotestflight.com/excuses/can-i-make-a-swift-wrapped-http-get-request-from-the-esp32c6/</link>
      <pubDate>Wed, 10 Sep 2025 00:00:00 +0000</pubDate>
      
      <guid>https://whynotestflight.com/excuses/can-i-make-a-swift-wrapped-http-get-request-from-the-esp32c6/</guid>
      <description>&lt;p&gt;So for this I created another component to act as a bridge.  Right now this turned out to be mostly C while I figure out how to / whether to bring in things like URL and URL session, HTTPRequest&amp;hellip;&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ve written &lt;a href=&#34;https://whynotestflight.com/excuses/mac-linux-everything-you-can-do...-i-can-do-somewhat/&#34;&gt;a client in Swift before&lt;/a&gt;, but it relied heavily on Foundation types. The only example in the the &lt;a href=&#34;https://github.com/swiftlang/swift-embedded-examples&#34;&gt;Swift Embedded  Examples&lt;/a&gt; repo that uses Foundation is a beautiful &lt;a href=&#34;https://github.com/apple/swift-mmio&#34;&gt;Swift MMIO&lt;/a&gt; based &lt;a href=&#34;https://github.com/swiftlang/swift-embedded-examples/tree/a1112f1d380653b6728edc2130b349d444ccd585/stm32-lvgl&#34;&gt;example for the stm32&lt;/a&gt; which is making me rethink my chip choices.  Although &lt;a href=&#34;https://www.disca.upv.es/aperles/arm_cortex_m3/curset/cmsis/documentation/SVD/html/index.html&#34;&gt;SVD data&lt;/a&gt; is &lt;a href=&#34;https://github.com/cmsis-svd/cmsis-svd-data/tree/main/data/Espressif&#34;&gt;available for the esp32c6&lt;/a&gt; even though it&amp;rsquo;s  &lt;a href=&#34;https://riscv.org&#34;&gt;RISCV&lt;/a&gt;, not &lt;a href=&#34;https://www.arm.com&#34;&gt;ARM&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;As an alternative to Foundation, &lt;a href=&#34;https://whynotestflight.com/tags/hummingbird/&#34;&gt;Hummingbird&lt;/a&gt; brings in &lt;a href=&#34;https://github.com/apple/swift-nio&#34;&gt;SwiftNIO&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Both Foundation and SwiftNIO are very large and I&amp;rsquo;m not in the mood to wrestle with the CMake file today.&lt;/p&gt;
&lt;p&gt;While I overthink this, I just made the proof of concept version with C.&lt;/p&gt;
&lt;h2 id=&#34;the-swift-files&#34;&gt;The Swift Files&lt;/h2&gt;
&lt;h3 id=&#34;mainswift&#34;&gt;Main.swift&lt;/h3&gt;
&lt;p&gt;Right above the while loop but after the delay to wait for the WiFi to connect&amp;hellip;&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-Swift&#34; data-lang=&#34;Swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//Waiting for wifi to connect...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  delay(&lt;span style=&#34;color:#f5a97f&#34;&gt;2000&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;client&lt;/span&gt; = HTTPClient()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  client.getAndPrint(from: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;example.com&amp;#34;&lt;/span&gt;, route: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;/&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;httpswift&#34;&gt;HTTP.swift&lt;/h3&gt;
&lt;p&gt;Again with the ugly string passing which I hope is temporary.&lt;/p&gt;
&lt;p&gt;THe result code is something I could turn into a thrown error at some point. It&amp;rsquo;s a really common pattern in C that the result is written at a shared pointer and the error code is the thing that&amp;rsquo;s returned.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-Swift&#34; data-lang=&#34;Swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;final&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;HTTPClient&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;getAndPrint&lt;/span&gt;(from host: &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;, route: &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Getting...&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(http_bridge_bridge_return_twelve())
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;local_host&lt;/span&gt; = host.utf8CString
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;local_route&lt;/span&gt; = route.utf8CString
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;TODO:&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt; test with span on beta?&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        local_route.withContiguousStorageIfAvailable { route_buffer &lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            local_host.withContiguousStorageIfAvailable { host_buffer &lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;resultCode&lt;/span&gt; = http_bridge_get(host_buffer.baseAddress, route_buffer.baseAddress)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;result code: &lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;resultCode&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;the-component-code&#34;&gt;The Component Code&lt;/h2&gt;
&lt;p&gt;The esp-idf has a &lt;a href=&#34;https://docs.espressif.com/projects/esp-idf/en/stable/esp32/api-reference/protocols/esp_http_client.html&#34;&gt;HTTP Client library&lt;/a&gt;, which a more robust version of this code could use. &lt;a href=&#34;https://github.com/espressif/esp-idf/tree/v5.5.1/examples/protocols/esp_http_client&#34;&gt;esp-idf example&lt;/a&gt;&lt;/p&gt;
&lt;h3 id=&#34;the-c-file&#34;&gt;The C File&lt;/h3&gt;
&lt;p&gt;Similar code is in the &lt;a href=&#34;https://github.com/espressif/esp-idf/blob/fcae32885b0296b32044cb99ecbdc50d98dddb83/examples/protocols/http_request/main/http_request_example_main.c#L38&#34;&gt;HTTP_Request example&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Both do the following basic steps:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;find out if the host name even exists as a valid URL&lt;/li&gt;
&lt;li&gt;make a socket&lt;/li&gt;
&lt;li&gt;use the socket to connect&lt;/li&gt;
&lt;li&gt;send the request over the socket&lt;/li&gt;
&lt;li&gt;say done sending&lt;/li&gt;
&lt;li&gt;receive the request&lt;/li&gt;
&lt;li&gt;&amp;hellip; the WHOLE request&lt;/li&gt;
&lt;li&gt;close the socket&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Making sure to close the socket in case of any failures as well.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-C&#34; data-lang=&#34;C&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;int&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;http_bridge_get&lt;/span&gt;(&lt;span style=&#34;color:#c6a0f6&#34;&gt;const&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;char&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;*&lt;/span&gt;host, &lt;span style=&#34;color:#c6a0f6&#34;&gt;const&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;char&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;*&lt;/span&gt;path) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#8aadf4&#34;&gt;printf&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;A&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;struct&lt;/span&gt; addrinfo hints &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        .ai_family &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; AF_INET,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        .ai_socktype &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; SOCK_STREAM,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    };
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;struct&lt;/span&gt; addrinfo &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;*&lt;/span&gt;res;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;int&lt;/span&gt; s;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#8aadf4&#34;&gt;printf&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;B&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;char&lt;/span&gt; port_str[] &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;80&amp;#34;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;int&lt;/span&gt; err &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;getaddrinfo&lt;/span&gt;(host, port_str, &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;amp;&lt;/span&gt;hints, &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;amp;&lt;/span&gt;res);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//int err = getaddrinfo(host, port_str, &amp;amp;hints, &amp;amp;res);
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; (err &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;!=&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;0&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;||&lt;/span&gt; res &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;==&lt;/span&gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;NULL&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#8aadf4&#34;&gt;printf&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;DNS lookup failed for %s&amp;#34;&lt;/span&gt;, host);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;1&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#8aadf4&#34;&gt;printf&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;C&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    s &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;socket&lt;/span&gt;(res&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;-&amp;gt;&lt;/span&gt;ai_family, res&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;-&amp;gt;&lt;/span&gt;ai_socktype, &lt;span style=&#34;color:#f5a97f&#34;&gt;0&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; (s &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;lt;&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;0&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#8aadf4&#34;&gt;printf&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;socket failed&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#8aadf4&#34;&gt;freeaddrinfo&lt;/span&gt;(res);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;2&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#8aadf4&#34;&gt;printf&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;D&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; (&lt;span style=&#34;color:#8aadf4&#34;&gt;connect&lt;/span&gt;(s, res&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;-&amp;gt;&lt;/span&gt;ai_addr, res&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;-&amp;gt;&lt;/span&gt;ai_addrlen) &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;!=&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;0&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#8aadf4&#34;&gt;printf&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;connect failed&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#8aadf4&#34;&gt;close&lt;/span&gt;(s);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#8aadf4&#34;&gt;freeaddrinfo&lt;/span&gt;(res);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;3&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#8aadf4&#34;&gt;printf&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;E&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#8aadf4&#34;&gt;freeaddrinfo&lt;/span&gt;(res);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#8aadf4&#34;&gt;printf&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;F&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;char&lt;/span&gt; req[&lt;span style=&#34;color:#f5a97f&#34;&gt;128&lt;/span&gt;];
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#8aadf4&#34;&gt;snprintf&lt;/span&gt;(req, &lt;span style=&#34;color:#c6a0f6&#34;&gt;sizeof&lt;/span&gt;(req),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;             &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;GET %s HTTP/1.0&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\r\n&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;             &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Host: %s&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\r\n&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;             &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;User-Agent: esp-idf/5.5&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\r\n&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;             &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\r\n&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;             path, host);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; (&lt;span style=&#34;color:#8aadf4&#34;&gt;write&lt;/span&gt;(s, req, &lt;span style=&#34;color:#8aadf4&#34;&gt;strlen&lt;/span&gt;(req)) &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;lt;&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;0&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#8aadf4&#34;&gt;printf&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;send failed&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#8aadf4&#34;&gt;close&lt;/span&gt;(s);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;4&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;char&lt;/span&gt; recv_buf[&lt;span style=&#34;color:#f5a97f&#34;&gt;512&lt;/span&gt;];
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;int&lt;/span&gt; r;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;while&lt;/span&gt; ((r &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;read&lt;/span&gt;(s, recv_buf, &lt;span style=&#34;color:#c6a0f6&#34;&gt;sizeof&lt;/span&gt;(recv_buf) &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;-&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;1&lt;/span&gt;)) &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;0&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        recv_buf[r] &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;0&lt;/span&gt;; &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// null terminate
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;        &lt;span style=&#34;color:#8aadf4&#34;&gt;printf&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;%s&amp;#34;&lt;/span&gt;, recv_buf);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#8aadf4&#34;&gt;close&lt;/span&gt;(s);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;0&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;the-header&#34;&gt;The header&lt;/h3&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-C&#34; data-lang=&#34;C&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#include&lt;/span&gt; &lt;span style=&#34;color:#6e738d;font-weight:bold;font-style:italic&#34;&gt;&amp;lt;string.h&amp;gt;&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#include&lt;/span&gt; &lt;span style=&#34;color:#6e738d;font-weight:bold;font-style:italic&#34;&gt;&amp;lt;sys/socket.h&amp;gt;&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#include&lt;/span&gt; &lt;span style=&#34;color:#6e738d;font-weight:bold;font-style:italic&#34;&gt;&amp;lt;netdb.h&amp;gt;   &lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;int&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;http_bridge_bridge_return_twelve&lt;/span&gt;(&lt;span style=&#34;color:#ed8796&#34;&gt;void&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;int&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;http_bridge_get&lt;/span&gt;(&lt;span style=&#34;color:#c6a0f6&#34;&gt;const&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;char&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;*&lt;/span&gt;host, &lt;span style=&#34;color:#c6a0f6&#34;&gt;const&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;char&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;*&lt;/span&gt;path);
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;the-cmake&#34;&gt;The CMake&lt;/h3&gt;
&lt;p&gt;No REQUIRED in this because the includes are part of the the C implementation.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-CMake&#34; data-lang=&#34;CMake&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#91d7e3&#34;&gt;idf_component_register&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;SRCS&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;http_bridge.c&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    &lt;span style=&#34;color:#a6da95&#34;&gt;INCLUDE_DIRS&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;include&amp;#34;&lt;/span&gt;)&lt;span style=&#34;color:#ed8796&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;summary&#34;&gt;Summary&lt;/h2&gt;
&lt;p&gt;Kinda punted on this part a bit while I figure out how much time I have to really dig in. Need to do some parts ordering, get the real server up, etc.&lt;/p&gt;
</description>
    </item>
    
    
    
    <item>
      <title>Can I add Wifi to the ESP32C6 project with Swift?</title>
      <link>https://whynotestflight.com/excuses/can-i-add-wifi-to-the-esp32c6-project-with-swift/</link>
      <pubDate>Tue, 09 Sep 2025 00:00:00 +0000</pubDate>
      
      <guid>https://whynotestflight.com/excuses/can-i-add-wifi-to-the-esp32c6-project-with-swift/</guid>
      <description>&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/carlynorama/swift_esp32c6_hello/tree/c_WiFi&#34;&gt;https://github.com/carlynorama/swift_esp32c6_hello/tree/c_WiFi&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I knew this was coming. Having to create a separate component. I tried to get Wifi working in the demo project without creating a bridge library but I couldn&amp;rsquo;t quite get the mismatch between what C elements Swift will compile inline and the C elements the SDK uses. (looking at you function style macros)&lt;/p&gt;
&lt;p&gt;I am going to put out there right now that there could be a better version of this code. I am not using &lt;a href=&#34;https://github.com/swiftlang/swift/blob/main/docs/HowSwiftImportsCAPIs.md&#34;&gt;all the C import features in Swift&lt;/a&gt; to minimize what&amp;rsquo;s in the bridging library. Nor am I using the &lt;a href=&#34;https://www.swift.org/documentation/cxx-interop/safe-interop/&#34;&gt;C decorators&lt;/a&gt; that make things safer &lt;a href=&#34;https://www.youtube.com/watch?v=fFPq_4_LCqo&#34;&gt;from WWDC25&lt;/a&gt;. &lt;a href=&#34;https://forums.swift.org/search?q=APINotes&#34;&gt;APINotes&lt;/a&gt; make no appearance at all. Those are all niceties for a future version. This is all about Wifi Hello World.&lt;/p&gt;
&lt;p&gt;Ultimately my solution is still a whole lot of C wrapped in a thin Swift shell, but it&amp;rsquo;s somewhere to start. It&amp;rsquo;s also just a concrete type. No &amp;ldquo;WifiProvider&amp;rdquo; protocol for now.&lt;/p&gt;
&lt;h3 id=&#34;useful-references&#34;&gt;Useful References:&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://espressif-docs.readthedocs-hosted.com/projects/idf-component-manager/en/latest/guides/packaging_components.html&#34;&gt;https://espressif-docs.readthedocs-hosted.com/projects/idf-component-manager/en/latest/guides/packaging_components.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://docs.espressif.com/projects/esp-idf/en/stable/esp32/api-guides/build-system.html&#34;&gt;https://docs.espressif.com/projects/esp-idf/en/stable/esp32/api-guides/build-system.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://docs.espressif.com/projects/esp-idf/en/stable/esp32/api-guides/build-system.html#writing-pure-cmake-components&#34;&gt;https://docs.espressif.com/projects/esp-idf/en/stable/esp32/api-guides/build-system.html#writing-pure-cmake-components&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://docs.espressif.com/projects/esp-idf/en/v5.5.1/esp32c6/api-guides/c.html&#34;&gt;https://docs.espressif.com/projects/esp-idf/en/v5.5.1/esp32c6/api-guides/c.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/rddevitte/esp-idf-sample-project/tree/master/components/output_pin_toggler&#34;&gt;https://github.com/rddevitte/esp-idf-sample-project/tree/master/components/output_pin_toggler&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;how-to-write-a-test-component&#34;&gt;How to write a Test Component&lt;/h2&gt;
&lt;p&gt;So there&amp;rsquo;s a whole page on &lt;a href=&#34;https://espressif-docs.readthedocs-hosted.com/projects/idf-component-manager/en/latest/guides/packaging_components.html&#34;&gt;how to write a test component&lt;/a&gt;, but I felt it left out some key details (or at least phrased them in away I didn&amp;rsquo;t grok) that I filled in just by looking at &lt;a href=&#34;https://github.com/rddevitte/esp-idf-sample-project/tree/master/components/output_pin_toggler&#34;&gt;someone elses demo&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Here is how I got my test component working with the Swift base. I did not have to touch the &lt;code&gt;CMakeLists.txt&lt;/code&gt; to add the library, &lt;a href=&#34;https://docs.espressif.com/projects/esp-idf/en/stable/esp32/api-guides/build-system.html#writing-pure-cmake-components&#34;&gt;although I could have&lt;/a&gt;. I relied on the esp-idf searching that in-project components folder for free. Didn&amp;rsquo;t even have to add the dependency to &lt;code&gt;/main/idf_component.yml&lt;/code&gt;.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#91d7e3&#34;&gt;cd&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;$CURRENT_PROJECT_DIR&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;mkdir -p components
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#91d7e3&#34;&gt;cd&lt;/span&gt; components
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;idf.py create-component test_cmp
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Then I updated the files to the following:&lt;/p&gt;
&lt;h3 id=&#34;componentstest_cmptest_cmpc&#34;&gt;/components/test_cmp/test_cmp.c&lt;/h3&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-C&#34; data-lang=&#34;C&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#include&lt;/span&gt; &lt;span style=&#34;color:#6e738d;font-weight:bold;font-style:italic&#34;&gt;&amp;lt;stdio.h&amp;gt;&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#include&lt;/span&gt; &lt;span style=&#34;color:#6e738d;font-weight:bold;font-style:italic&#34;&gt;&amp;#34;test_cmp.h&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// One of my go to canary functions.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;int&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;test_cmp_return_twelve&lt;/span&gt;(&lt;span style=&#34;color:#ed8796&#34;&gt;void&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;12&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;componentstest_cmpincludetest_cmph&#34;&gt;/components/test_cmp/include/test_cmp.h&lt;/h3&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-C&#34; data-lang=&#34;C&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;int&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;test_cmp__return_twelve&lt;/span&gt;(&lt;span style=&#34;color:#ed8796&#34;&gt;void&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;componentstest_cmpcmakeliststxt&#34;&gt;/components/test_cmp/CMakeLists.txt&lt;/h3&gt;
&lt;p&gt;left unchanged.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-CMake&#34; data-lang=&#34;CMake&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#91d7e3&#34;&gt;idf_component_register&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;SRCS&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;test_cmp.c&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    &lt;span style=&#34;color:#a6da95&#34;&gt;INCLUDE_DIRS&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;include&amp;#34;&lt;/span&gt;)&lt;span style=&#34;color:#ed8796&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;mainbridgingheaderh&#34;&gt;/main/BridgingHeader.h&lt;/h3&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-C&#34; data-lang=&#34;C&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//existing items....
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#include&lt;/span&gt; &lt;span style=&#34;color:#6e738d;font-weight:bold;font-style:italic&#34;&gt;&amp;#34;test_cmp.h&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;mainmainswift&#34;&gt;/main/Main.swift&lt;/h3&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-Swift&#34; data-lang=&#34;Swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;@_cdecl(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;app_main&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;main&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//before...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(test_cmp_return_twelve())
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//..etc&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#c6a0f6&#34;&gt;while&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;true&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//etc.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;wifi-component-in-the-project&#34;&gt;Wifi Component In the Project&lt;/h2&gt;
&lt;p&gt;So I &lt;a href=&#34;https://github.com/carlynorama/swift_esp32c6_hello/commit/2cfc0fd7d1ddfe3d516d63b768b2e77e10ef5bda&#34;&gt;started with a simple&lt;/a&gt; version, but it was having trouble. What didn&amp;rsquo;t occur to me until much later was that the symptoms I was seeing lined up with the code reacting poorly with the USB startup processes. The esp-idf driven code (sdk and monitor) handles that all so automagically. (print just works! With no Serial.begin or anything!), it just wasn&amp;rsquo;t on my radar to factor that in until todbot mentioned it.&lt;/p&gt;
&lt;p&gt;I made two other working but more complicated versions to try to troubleshoot that can be seen in the git history:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&amp;ldquo;&lt;a href=&#34;https://github.com/carlynorama/swift_esp32c6_hello/commit/145b05fd4488f1a6e1a42e2d5327d7a7f817dd93&#34;&gt;common works&lt;/a&gt;&amp;rdquo;: One that pulls the &lt;a href=&#34;https://github.com/espressif/esp-idf/tree/v5.5.1/examples/common_components/protocol_examples_common&#34;&gt;protocols_examples_common&lt;/a&gt; component out of the example folder (drives the example in the &lt;a href=&#34;https://github.com/espressif/esp-idf/tree/v5.5.1/examples/protocols&#34;&gt;protocol&lt;/a&gt; folder.)&lt;/li&gt;
&lt;li&gt;&amp;ldquo;&lt;a href=&#34;https://github.com/carlynorama/swift_esp32c6_hello/commit/a6918fac548bb3e239cd2bdc8ec857635664f2cb&#34;&gt;works like station example&lt;/a&gt;&amp;rdquo;: One that pulls the event based functions from the &lt;a href=&#34;https://github.com/espressif/esp-idf/tree/v5.5.1/examples/wifi/getting_started/station&#34;&gt;station&lt;/a&gt; wifi getting started example.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Those both work, but since this is all for demo code more than a targeting having a robust WiFi library, I really wanted to make the simple iteration happen.&lt;/p&gt;
&lt;p&gt;The &lt;a href=&#34;https://github.com/carlynorama/swift_esp32c6_hello/tree/c_WiFi&#34;&gt;code current to this post&lt;/a&gt; works by adding delays in the &lt;code&gt;Main.swift&lt;/code&gt;, it does not recover from a disconnect. It does not retry. It&amp;rsquo;s not GOOD wifi code, but only essential. (minus a deinit).&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-Swift&#34; data-lang=&#34;Swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;@_cdecl(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;app_main&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;main&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#c6a0f6&#34;&gt;guard&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;led&lt;/span&gt; = DigitalIndicator(&lt;span style=&#34;color:#f5a97f&#34;&gt;15&lt;/span&gt;) &lt;span style=&#34;color:#c6a0f6&#34;&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#91d7e3&#34;&gt;fatalError&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Difficulty setting up pin.&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#c6a0f6&#34;&gt;guard&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;button&lt;/span&gt; = MomentaryInput(&lt;span style=&#34;color:#f5a97f&#34;&gt;9&lt;/span&gt;) &lt;span style=&#34;color:#c6a0f6&#34;&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#91d7e3&#34;&gt;fatalError&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Difficulty setting up button.&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//Waiting for USB...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  delay(&lt;span style=&#34;color:#f5a97f&#34;&gt;2000&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Hello from Swift on ESP32-C6!&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(wifi_bridge_return_twelve())
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;wifi&lt;/span&gt; = WiFiStation()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  wifi.connect(ssid: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;somenetwork&amp;#34;&lt;/span&gt;, password: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;somepassword&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//Waiting for wifi to connect...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  delay(&lt;span style=&#34;color:#f5a97f&#34;&gt;2000&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#c6a0f6&#34;&gt;while&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;true&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; button.isActive {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      led.blink(millis: &lt;span style=&#34;color:#f5a97f&#34;&gt;500&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    } &lt;span style=&#34;color:#c6a0f6&#34;&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      led.blink(millis: &lt;span style=&#34;color:#f5a97f&#34;&gt;2000&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;It&amp;rsquo;s an old solution. But it checks out.&lt;/p&gt;
&lt;h3 id=&#34;wifiswift&#34;&gt;Wifi.swift&lt;/h3&gt;
&lt;p&gt;Getting a cleaner version of the string passing from Swift into C might be more possible on a &lt;a href=&#34;https://forums.swift.org/t/supporting-span-in-packages/81667&#34;&gt;machine running macOS 26&lt;/a&gt;? The &lt;a href=&#34;https://www.swift.org/documentation/cxx-interop/safe-interop/&#34;&gt;C-Interop safety&lt;/a&gt; &lt;a href=&#34;https://clang.llvm.org/docs/BoundsSafety.html&#34;&gt;features&lt;/a&gt; with &lt;a href=&#34;https://developer.apple.com/documentation/swift/span&#34;&gt;spans&lt;/a&gt; weren&amp;rsquo;t quite working correctly. (Could decorate the C, wasn&amp;rsquo;t being acknowledge by the Swift.)&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-Swift&#34; data-lang=&#34;Swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;final&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;WiFiStation&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;init&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        checkWithFatal(wifi_bridge_initialize_nvs())
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        checkWithFatal(wifi_bridge_initialize_netif())
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        checkWithFatal(wifi_bridge_wifi_init_default_config())
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;connect&lt;/span&gt;(ssid: &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;, password: &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//     currentSSID = ssid&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//     currentPassword = password&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;local_ssid&lt;/span&gt; = ssid.utf8CString
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;local_pass&lt;/span&gt; = password.utf8CString
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;TODO:&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt; test with span on beta? &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// Span was not rendering with 6.2 Sept 6 snapshot and lifetime. &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        local_pass.withContiguousStorageIfAvailable { pass_buffer &lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            local_ssid.withContiguousStorageIfAvailable { ssid_buffer &lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                checkWithFatal(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    wifi_bridge_wifi_set_config_and_connect(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                        ssid_buffer.baseAddress, pass_buffer.baseAddress))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// Compiles, runs, but spits out garbage.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// checkWithFatal(wifi_bridge_wifi_set_config_and_connect(&amp;amp;local_ssid, &amp;amp;local_pass))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;errorhandlerswift&#34;&gt;ErrorHandler.swift&lt;/h3&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-Swift&#34; data-lang=&#34;Swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;typealias&lt;/span&gt; SDKError = esp_err_t
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;checkWithFatal&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; error:SDKError, message:&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;guard&lt;/span&gt; error == ESP_OK &lt;span style=&#34;color:#c6a0f6&#34;&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#91d7e3&#34;&gt;fatalError&lt;/span&gt;(message)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;checkWithFatal&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; error:SDKError) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;guard&lt;/span&gt; error == ESP_OK &lt;span style=&#34;color:#c6a0f6&#34;&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#91d7e3&#34;&gt;fatalError&lt;/span&gt;(&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;(cString:esp_err_to_name(error)))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;checkWithThrow&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; error:SDKError, &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; swiftError: some Error) &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;guard&lt;/span&gt; error == ESP_OK &lt;span style=&#34;color:#c6a0f6&#34;&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;throw&lt;/span&gt;(swiftError)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;checkWithThrow&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; error:SDKError) &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;guard&lt;/span&gt; error == ESP_OK &lt;span style=&#34;color:#c6a0f6&#34;&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;throw&lt;/span&gt;(SDKErrorWrapper.passMessage(&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;(cString:esp_err_to_name(error))))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;enum&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;SDKErrorWrapper&lt;/span&gt;:Error {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;case&lt;/span&gt; passMessage(&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;component-internals&#34;&gt;Component Internals&lt;/h3&gt;
&lt;p&gt;This is what the project layout looks like with the component now.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;|- components
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;|  |- wifi_bridge
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;|  |  |- include
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;|  |  |  |- wifi_bridge.h
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;|  |  |- CMakeLists.txt
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;|  |  |- common_config.txt (vestigial from previous version)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;|  |  |- idf_component.yml (needs to be updated)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;|  |  |- wifi_bridge.c 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;|- main
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;|  |- Bool_Int.swift
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;|  |- BridgingHeader.swift
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;|  |- CMakeLists.txt
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;|  |- Delay.swift
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;|  |- DigitalIndicator.swift
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;|  |- ErrorHandler.swift
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;|  |- GPIOPin.swift
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;|  |- Main.swift
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;|  |- MomentaryInput.swift
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;|  |- Wifi.swift
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;|  |- idf_component.yml
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;|
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;|- CMakeLists.txt
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;|- .gitignore
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;wifi_bridgeh&#34;&gt;wifi_bridge.h&lt;/h3&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-C&#34; data-lang=&#34;C&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#include&lt;/span&gt; &lt;span style=&#34;color:#6e738d;font-weight:bold;font-style:italic&#34;&gt;&amp;lt;string.h&amp;gt;&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#include&lt;/span&gt; &lt;span style=&#34;color:#6e738d;font-weight:bold;font-style:italic&#34;&gt;&amp;#34;esp_wifi.h&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#include&lt;/span&gt; &lt;span style=&#34;color:#6e738d;font-weight:bold;font-style:italic&#34;&gt;&amp;#34;esp_event.h&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#include&lt;/span&gt; &lt;span style=&#34;color:#6e738d;font-weight:bold;font-style:italic&#34;&gt;&amp;#34;esp_log.h&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#include&lt;/span&gt; &lt;span style=&#34;color:#6e738d;font-weight:bold;font-style:italic&#34;&gt;&amp;#34;nvs_flash.h&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;int&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;wifi_bridge_return_twelve&lt;/span&gt;(&lt;span style=&#34;color:#ed8796&#34;&gt;void&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;void&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;test_string_passing&lt;/span&gt;(&lt;span style=&#34;color:#c6a0f6&#34;&gt;const&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;char&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;*&lt;/span&gt;bridge_first, &lt;span style=&#34;color:#c6a0f6&#34;&gt;const&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;char&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;*&lt;/span&gt;bridge_last);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;esp_err_t&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;wifi_bridge_initialize_nvs&lt;/span&gt;(&lt;span style=&#34;color:#ed8796&#34;&gt;void&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;esp_err_t&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;wifi_bridge_initialize_netif&lt;/span&gt;(&lt;span style=&#34;color:#ed8796&#34;&gt;void&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;esp_err_t&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;wifi_bridge_wifi_init_default_config&lt;/span&gt;(&lt;span style=&#34;color:#ed8796&#34;&gt;void&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;esp_err_t&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;wifi_bridge_wifi_set_config_and_connect&lt;/span&gt;(&lt;span style=&#34;color:#c6a0f6&#34;&gt;const&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;char&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;*&lt;/span&gt;wifi_ssid, &lt;span style=&#34;color:#c6a0f6&#34;&gt;const&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;char&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;*&lt;/span&gt;wifi_pass);
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;wifi_bridgec&#34;&gt;wifi_bridge.c&lt;/h3&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-C&#34; data-lang=&#34;C&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#include&lt;/span&gt; &lt;span style=&#34;color:#6e738d;font-weight:bold;font-style:italic&#34;&gt;&amp;#34;wifi_bridge.h&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;int&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;wifi_bridge_return_twelve&lt;/span&gt;(&lt;span style=&#34;color:#ed8796&#34;&gt;void&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;12&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;esp_err_t&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;wifi_bridge_initialize_nvs&lt;/span&gt;(&lt;span style=&#34;color:#ed8796&#34;&gt;void&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;esp_err_t&lt;/span&gt; ret &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;nvs_flash_init&lt;/span&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; (ret &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;==&lt;/span&gt; ESP_ERR_NVS_NO_FREE_PAGES &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;||&lt;/span&gt; ret &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;==&lt;/span&gt; ESP_ERR_NVS_NEW_VERSION_FOUND) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;esp_err_t&lt;/span&gt; flash_ret &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;nvs_flash_erase&lt;/span&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; (flash_ret &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;==&lt;/span&gt; ESP_OK) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;             ret &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;nvs_flash_init&lt;/span&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        } &lt;span style=&#34;color:#c6a0f6&#34;&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            ret &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; flash_ret;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; ret;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//TODO: what if needed that pointer later? 
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;esp_err_t&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;wifi_bridge_initialize_netif&lt;/span&gt;(&lt;span style=&#34;color:#ed8796&#34;&gt;void&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;esp_err_t&lt;/span&gt; ret &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;esp_netif_init&lt;/span&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; (ret &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;==&lt;/span&gt; ESP_OK) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        ret &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;esp_event_loop_create_default&lt;/span&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;esp_netif_t&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;*&lt;/span&gt;sta_netif &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;esp_netif_create_default_wifi_sta&lt;/span&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#8aadf4&#34;&gt;assert&lt;/span&gt;(sta_netif);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; ret ;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;esp_err_t&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;wifi_bridge_wifi_init_default_config&lt;/span&gt;(&lt;span style=&#34;color:#ed8796&#34;&gt;void&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;wifi_init_config_t&lt;/span&gt; cfg &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;WIFI_INIT_CONFIG_DEFAULT&lt;/span&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;esp_wifi_init&lt;/span&gt;(&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;amp;&lt;/span&gt;cfg);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// #define TMP_SSID &amp;#34;example&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// #define TMP_PASS &amp;#34;example&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//strings don&amp;#39;t actually work
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;esp_err_t&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;wifi_bridge_wifi_set_config_and_connect&lt;/span&gt;(&lt;span style=&#34;color:#c6a0f6&#34;&gt;const&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;char&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;*&lt;/span&gt;wifi_ssid, &lt;span style=&#34;color:#c6a0f6&#34;&gt;const&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;char&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;*&lt;/span&gt;wifi_pass) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//uint8_t ssid[32]
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//uint8_t password[64]
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// wifi_config_t wifi_config = {
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//      .sta = { 
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//          .ssid = TMP_SSID, 
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//          .password = TMP_PASS, 
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//      }, 
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//  }; 
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#8aadf4&#34;&gt;printf&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;ssid: %s, pass: %s&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\n&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;, wifi_ssid, wifi_pass);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;wifi_config_t&lt;/span&gt; wifi_config &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; {&lt;span style=&#34;color:#f5a97f&#34;&gt;0&lt;/span&gt;}; &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// empty config
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// //count is the maximum 
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#8aadf4&#34;&gt;strncpy&lt;/span&gt;((&lt;span style=&#34;color:#ed8796&#34;&gt;char&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;*&lt;/span&gt;)wifi_config.sta.ssid, wifi_ssid, &lt;span style=&#34;color:#c6a0f6&#34;&gt;sizeof&lt;/span&gt;(wifi_config.sta.ssid));
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#8aadf4&#34;&gt;strncpy&lt;/span&gt;((&lt;span style=&#34;color:#ed8796&#34;&gt;char&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;*&lt;/span&gt;)wifi_config.sta.password, wifi_pass, &lt;span style=&#34;color:#c6a0f6&#34;&gt;sizeof&lt;/span&gt;(wifi_config.sta.password));
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;esp_err_t&lt;/span&gt; ret &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;esp_wifi_set_mode&lt;/span&gt;(WIFI_MODE_STA);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; (ret &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;==&lt;/span&gt; ESP_OK) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        ret &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;esp_wifi_set_config&lt;/span&gt;(WIFI_IF_STA, &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;amp;&lt;/span&gt;wifi_config);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    } &lt;span style=&#34;color:#c6a0f6&#34;&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; ret;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; (ret &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;==&lt;/span&gt; ESP_OK) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        ret &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;esp_wifi_start&lt;/span&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    } &lt;span style=&#34;color:#c6a0f6&#34;&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; ret;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; (ret &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;==&lt;/span&gt; ESP_OK) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        ret &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;esp_wifi_connect&lt;/span&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    } &lt;span style=&#34;color:#c6a0f6&#34;&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; ret;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; ret;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;cmakeliststxt&#34;&gt;CMakeLists.txt&lt;/h3&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-CMake&#34; data-lang=&#34;CMake&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#91d7e3&#34;&gt;idf_component_register&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;SRCS&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;wifi_bridge.c&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    &lt;span style=&#34;color:#a6da95&#34;&gt;PRIV_REQUIRES&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;esp_wifi&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;nvs_flash&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;esp_netif&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    &lt;span style=&#34;color:#a6da95&#34;&gt;INCLUDE_DIRS&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;include&amp;#34;&lt;/span&gt;)&lt;span style=&#34;color:#ed8796&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;summary&#34;&gt;Summary&lt;/h2&gt;
&lt;p&gt;Went through some dead end investigations that I think will have served me well in the future. An HTTP get request is next!&lt;/p&gt;
</description>
    </item>
    
    
    
    <item>
      <title>Can I combine an LED and a button on the ESP32C6 with Swift?</title>
      <link>https://whynotestflight.com/excuses/can-i-combine-an-led-and-a-button-on-the-esp32c6-with-swift/</link>
      <pubDate>Mon, 08 Sep 2025 00:00:00 +0000</pubDate>
      
      <guid>https://whynotestflight.com/excuses/can-i-combine-an-led-and-a-button-on-the-esp32c6-with-swift/</guid>
      <description>&lt;p&gt;So I wasn&amp;rsquo;t satisfied with just adding a switch to &lt;a href=&#34;https://github.com/swiftlang/swift-embedded-examples/tree/main/esp32-led-blink-sdk&#34;&gt;the existing demo&lt;/a&gt;&amp;hellip; I had to start making it fancier.&lt;/p&gt;
&lt;p&gt;For some reason right about when I switched to writing my own Swift code my &lt;code&gt;esp-idf&lt;/code&gt; install stopped working? It took me awhile to realize to was the tooling, not my code. The idf was handing out error messages about the creation of &lt;code&gt;project_description.json&lt;/code&gt; on ALL projects and &lt;code&gt;idf.py menuconfig&lt;/code&gt; crashed hard in multi-colored glory when called, even on examples that worked previously.&lt;/p&gt;
&lt;p&gt;I reinstalled the whole esp-idf again and everything worked fine. I&amp;rsquo;m not sure if it was a software update overnight on my computer or if my spelunking around in that folder did something. Thank goodness for high speed internet because that was another big download.&lt;/p&gt;
&lt;p&gt;After all that I ended up with two more steps of the project done:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;rewriting the base: &lt;a href=&#34;https://github.com/carlynorama/swift_esp32c6_hello/tree/a_start_with_LED&#34;&gt;https://github.com/carlynorama/swift_esp32c6_hello/tree/a_start_with_LED&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;adding a switch: &lt;a href=&#34;https://github.com/carlynorama/swift_esp32c6_hello/tree/b_add_a_switch&#34;&gt;https://github.com/carlynorama/swift_esp32c6_hello/tree/b_add_a_switch&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Compare to:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;PicoW Version from Last Year: &lt;a href=&#34;https://github.com/carlynorama/swift-pico-w-hello/tree/main/01-OnboardLED&#34;&gt;https://github.com/carlynorama/swift-pico-w-hello/tree/main/01-OnboardLED&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;PicoW Version from Last Year: &lt;a href=&#34;https://github.com/carlynorama/swift-pico-w-hello/tree/main/02-Switch&#34;&gt;https://github.com/carlynorama/swift-pico-w-hello/tree/main/02-Switch&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Base project: &lt;a href=&#34;https://github.com/swiftlang/swift-embedded-examples/tree/main/esp32-led-blink-sdk&#34;&gt;https://github.com/swiftlang/swift-embedded-examples/tree/main/esp32-led-blink-sdk&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;project-anatomy&#34;&gt;Project Anatomy&lt;/h2&gt;
&lt;p&gt;I&amp;rsquo;m going to focus on recapping the project with both the LED and the button working, which has the following files:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;|- main
|  |- Bool_Int.swift
|  |- BridgingHeader.swift
|  |- CMakeLists.txt
|  |- Delay.swift
|  |- DigitalIndicator.swift
|  |- MomentaryInput.swift
|  |- GPIOPin.swift
|  |- Main.swift
|  |- idf_component.yml
|
|- CMakeLists.txt
|- .gitignore
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;All of these files were added by hand to main/CMakeLists.txt&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-CMake&#34; data-lang=&#34;CMake&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# List of Swift source files to build.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#91d7e3&#34;&gt;target_sources&lt;/span&gt;(&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;${&lt;/span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;COMPONENT_LIB&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6da95&#34;&gt;PRIVATE&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6da95&#34;&gt;Main.swift&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6da95&#34;&gt;Bool_Int.swift&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6da95&#34;&gt;GPIOPin.swift&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6da95&#34;&gt;DigitalIndicator.swift&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6da95&#34;&gt;MomentaryInput.swift&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6da95&#34;&gt;Delay.swift&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;)&lt;span style=&#34;color:#ed8796&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;mainswift&#34;&gt;Main.swift&lt;/h2&gt;
&lt;p&gt;Notice that the only call directly backed by the  esp32C6 sdk is &lt;code&gt;print&lt;/code&gt;, many SDK&amp;rsquo;s implement print &lt;a href=&#34;https://github.com/swiftlang/swift-embedded-examples/blob/0ea13632cbf671d2b514f8c020db4bb042f55554/Sources/EmbeddedSwift/Documentation.docc/SDKSupport/IntegratingWithPlatforms.md?plain=1#L93&#34;&gt;but it isn&amp;rsquo;t guaranteed&lt;/a&gt;. &lt;code&gt;ESP_LOG&lt;/code&gt; and &lt;code&gt;print&lt;/code&gt; do not behave identically. That&amp;rsquo;s its own post!  What we do have is a &lt;code&gt;DigitalIndicator&lt;/code&gt; type and a &lt;code&gt;MomentaryInput&lt;/code&gt; type.  I think it&amp;rsquo;s possible those would be better as protocols (&lt;code&gt;DigitallyIndicating&lt;/code&gt; and ``DigitalReceiving`?), but for now they&amp;rsquo;re concrete types.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-Swift&#34; data-lang=&#34;Swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;@_cdecl(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;app_main&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;main&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Hello from Swift on ESP32-C6!&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#c6a0f6&#34;&gt;guard&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;led&lt;/span&gt; = DigitalIndicator(&lt;span style=&#34;color:#f5a97f&#34;&gt;15&lt;/span&gt;) &lt;span style=&#34;color:#c6a0f6&#34;&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#91d7e3&#34;&gt;fatalError&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Difficulty setting up pin.&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#c6a0f6&#34;&gt;guard&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;button&lt;/span&gt; = MomentaryInput(&lt;span style=&#34;color:#f5a97f&#34;&gt;9&lt;/span&gt;) &lt;span style=&#34;color:#c6a0f6&#34;&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#91d7e3&#34;&gt;fatalError&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Difficulty setting up button.&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#c6a0f6&#34;&gt;while&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;true&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; button.isActive {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      led.blink(millis: &lt;span style=&#34;color:#f5a97f&#34;&gt;500&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    } &lt;span style=&#34;color:#c6a0f6&#34;&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      led.blink(millis: &lt;span style=&#34;color:#f5a97f&#34;&gt;2000&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;digitalindicatorswift&#34;&gt;DigitalIndicator.swift&lt;/h2&gt;
&lt;p&gt;Also NO esp32c6 specific code&lt;/p&gt;
&lt;p&gt;A DigitalIndicator has some more things defined&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;OutputPin&lt;/code&gt;: currently concrete implementation of the GPIOPin protocol, GPIOPin.swift&lt;/li&gt;
&lt;li&gt;&lt;code&gt;GPIOLevel&lt;/code&gt; a binary enum with cases (.high, .low), GPIOPin.swift&lt;/li&gt;
&lt;li&gt;&lt;code&gt;delay(_:millis:UInt32)&lt;/code&gt;,  Delay.swift&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-Swift&#34; data-lang=&#34;Swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;DigitalIndicator&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;pin&lt;/span&gt;:OutputPin 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;activeLevel&lt;/span&gt;: GPIOLevel
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;expectedState&lt;/span&gt;: &lt;span style=&#34;color:#91d7e3&#34;&gt;Bool&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;set&lt;/span&gt;(on:&lt;span style=&#34;color:#91d7e3&#34;&gt;Bool&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;level&lt;/span&gt; = on ? activeLevel.asBool : &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;!&lt;/span&gt;activeLevel.asBool
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        pin.setLevel(levelHigh:level)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;mutating&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;turnOn&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;.&lt;span style=&#34;color:#c6a0f6&#34;&gt;set&lt;/span&gt;(on: &lt;span style=&#34;color:#f5a97f&#34;&gt;true&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        expectedState = &lt;span style=&#34;color:#f5a97f&#34;&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;mutating&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;turnOff&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;.&lt;span style=&#34;color:#c6a0f6&#34;&gt;set&lt;/span&gt;(on: &lt;span style=&#34;color:#f5a97f&#34;&gt;false&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        expectedState = &lt;span style=&#34;color:#f5a97f&#34;&gt;false&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;mutating&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;toggle&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;level&lt;/span&gt;: &lt;span style=&#34;color:#91d7e3&#34;&gt;Bool&lt;/span&gt; = expectedState ? &lt;span style=&#34;color:#f5a97f&#34;&gt;false&lt;/span&gt; : &lt;span style=&#34;color:#f5a97f&#34;&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;.&lt;span style=&#34;color:#c6a0f6&#34;&gt;set&lt;/span&gt;(on: level)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        expectedState = level
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;mutating&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;blink&lt;/span&gt;(millis:&lt;span style=&#34;color:#91d7e3&#34;&gt;UInt32&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;.toggle()  &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// Toggle the boolean value&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        delay(millis)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;mutating&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;blink&lt;/span&gt;(onMillis:&lt;span style=&#34;color:#91d7e3&#34;&gt;UInt32&lt;/span&gt;, offMillis:&lt;span style=&#34;color:#91d7e3&#34;&gt;UInt32&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;.turnOn()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        delay(onMillis)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;.turnOff()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        delay(offMillis)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;extension&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;DigitalIndicator&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;init&lt;/span&gt;?(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; pinNum: &lt;span style=&#34;color:#91d7e3&#34;&gt;UInt32&lt;/span&gt;, activeLow:&lt;span style=&#34;color:#91d7e3&#34;&gt;Bool&lt;/span&gt; = &lt;span style=&#34;color:#f5a97f&#34;&gt;true&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;.pin = OutputPin(pinNumber: pinNum, activeLow:activeLow)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;.activeLevel = GPIOLevel(&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;!&lt;/span&gt;activeLow)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;.expectedState = &lt;span style=&#34;color:#f5a97f&#34;&gt;false&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;delayswift&#34;&gt;Delay.swift&lt;/h2&gt;
&lt;p&gt;A ESP32C6 specific implementation of a delay function. TODO: why did the demo code use &lt;code&gt;configTICK_RATE_HZ&lt;/code&gt; instead of &lt;code&gt;portTICK_PERIOD_MS&lt;/code&gt;?&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-Swift&#34; data-lang=&#34;Swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;delay&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; millis:&lt;span style=&#34;color:#91d7e3&#34;&gt;UInt32&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    vTaskDelay(millis &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;/&lt;/span&gt; (&lt;span style=&#34;color:#f5a97f&#34;&gt;1000&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;/&lt;/span&gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;UInt32&lt;/span&gt;(configTICK_RATE_HZ)))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;gpiopinswiftgpiolevel-and-bool_intswift&#34;&gt;GPIOPin.swift:GPIOLevel and Bool_Int.swift&lt;/h2&gt;
&lt;p&gt;No esp32c6 specific code. But maybe it could. Considering creating a typealias for archInt and archUInt.&lt;/p&gt;
&lt;p&gt;These two work to clarify that &lt;code&gt;1&lt;/code&gt;, &lt;code&gt;true&lt;/code&gt; and &lt;code&gt;.high&lt;/code&gt; all mean the same thing, and to translate C&amp;rsquo;s &lt;code&gt;1&lt;/code&gt;/&lt;code&gt;0&lt;/code&gt; returns to &lt;code&gt;true&lt;/code&gt;/&lt;code&gt;false&lt;/code&gt; easily as needed.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-Swift&#34; data-lang=&#34;Swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;TODO:&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt; raw value? Bool or UInt32? &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;enum&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;GPIOLevel&lt;/span&gt;:&lt;span style=&#34;color:#91d7e3&#34;&gt;Equatable&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;case&lt;/span&gt; high
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;case&lt;/span&gt; low
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;extension&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;GPIOLevel&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;init&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; v:&lt;span style=&#34;color:#91d7e3&#34;&gt;Int32&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; v == &lt;span style=&#34;color:#f5a97f&#34;&gt;0&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt; = .low
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        } &lt;span style=&#34;color:#c6a0f6&#34;&gt;else&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; v == &lt;span style=&#34;color:#f5a97f&#34;&gt;1&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt; = .high
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        } &lt;span style=&#34;color:#c6a0f6&#34;&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#91d7e3&#34;&gt;fatalError&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Expected 0 or 1, got &lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;v&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;init&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; v:&lt;span style=&#34;color:#91d7e3&#34;&gt;UInt32&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; v == &lt;span style=&#34;color:#f5a97f&#34;&gt;0&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt; = .low
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        } &lt;span style=&#34;color:#c6a0f6&#34;&gt;else&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; v == &lt;span style=&#34;color:#f5a97f&#34;&gt;1&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt; = .high
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        } &lt;span style=&#34;color:#c6a0f6&#34;&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#91d7e3&#34;&gt;fatalError&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Expected 0 or 1, got &lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;v&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;init&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; v:&lt;span style=&#34;color:#91d7e3&#34;&gt;Bool&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; v == &lt;span style=&#34;color:#f5a97f&#34;&gt;false&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt; = .low
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        } &lt;span style=&#34;color:#c6a0f6&#34;&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt; = .high
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;asUInt32&lt;/span&gt;:&lt;span style=&#34;color:#91d7e3&#34;&gt;UInt32&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        (&lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt; == .high) ? &lt;span style=&#34;color:#f5a97f&#34;&gt;1&lt;/span&gt; : &lt;span style=&#34;color:#f5a97f&#34;&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;asInt32&lt;/span&gt;:&lt;span style=&#34;color:#91d7e3&#34;&gt;Int32&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        (&lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt; == .high) ? &lt;span style=&#34;color:#f5a97f&#34;&gt;1&lt;/span&gt; : &lt;span style=&#34;color:#f5a97f&#34;&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;asBool&lt;/span&gt;:&lt;span style=&#34;color:#91d7e3&#34;&gt;Bool&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        (&lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt; == .high) ? &lt;span style=&#34;color:#f5a97f&#34;&gt;true&lt;/span&gt; : &lt;span style=&#34;color:#f5a97f&#34;&gt;false&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;extension&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;Bool&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;init&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; v:&lt;span style=&#34;color:#91d7e3&#34;&gt;UInt32&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; v == &lt;span style=&#34;color:#f5a97f&#34;&gt;0&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt; = &lt;span style=&#34;color:#f5a97f&#34;&gt;false&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        } &lt;span style=&#34;color:#c6a0f6&#34;&gt;else&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; v == &lt;span style=&#34;color:#f5a97f&#34;&gt;1&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt; = &lt;span style=&#34;color:#f5a97f&#34;&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        } &lt;span style=&#34;color:#c6a0f6&#34;&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#91d7e3&#34;&gt;fatalError&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Expected 0 or 1, got &lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;v&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;init&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; v:&lt;span style=&#34;color:#91d7e3&#34;&gt;Int32&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; v == &lt;span style=&#34;color:#f5a97f&#34;&gt;0&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt; = &lt;span style=&#34;color:#f5a97f&#34;&gt;false&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        } &lt;span style=&#34;color:#c6a0f6&#34;&gt;else&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; v == &lt;span style=&#34;color:#f5a97f&#34;&gt;1&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt; = &lt;span style=&#34;color:#f5a97f&#34;&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        } &lt;span style=&#34;color:#c6a0f6&#34;&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#91d7e3&#34;&gt;fatalError&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Expected 0 or 1, got &lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;v&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;asUInt32&lt;/span&gt;:&lt;span style=&#34;color:#91d7e3&#34;&gt;UInt32&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt; ? &lt;span style=&#34;color:#f5a97f&#34;&gt;1&lt;/span&gt; : &lt;span style=&#34;color:#f5a97f&#34;&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;gpiopinswiftgpiodirection&#34;&gt;GPIOPin.swift:GPIODirection&lt;/h2&gt;
&lt;p&gt;This has a esp32C6 dynamic var, could be an extension in sub package.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-Swift&#34; data-lang=&#34;Swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;enum&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;GPIODirection&lt;/span&gt;  {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;case&lt;/span&gt; input
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;case&lt;/span&gt; output
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//esp32C6 implementation&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;extension&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;GPIODirection&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;esp32C6&lt;/span&gt;:gpio_mode_t {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;switch&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;case&lt;/span&gt; .input: 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; GPIO_MODE_INPUT
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;case&lt;/span&gt; .output: 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; GPIO_MODE_OUTPUT
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;gpiopinswiftgpiopin&#34;&gt;GPIOPin.swift:GPIOPin&lt;/h2&gt;
&lt;p&gt;GPIOPin is a protocol&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-Swift&#34; data-lang=&#34;Swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;protocol&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;GPIOPin&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;pinNumber&lt;/span&gt;:&lt;span style=&#34;color:#91d7e3&#34;&gt;UInt32&lt;/span&gt; { &lt;span style=&#34;color:#c6a0f6&#34;&gt;get&lt;/span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;direction&lt;/span&gt;: GPIODirection { &lt;span style=&#34;color:#c6a0f6&#34;&gt;get&lt;/span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;gpiopinswiftoutputpin&#34;&gt;GPIOPin.swift:OutputPin&lt;/h2&gt;
&lt;p&gt;I decided to make OutputPin a &lt;code&gt;Struct&lt;/code&gt; (esp32c6 specific) rather than a &lt;code&gt;Protocol&lt;/code&gt; for now because I didn&amp;rsquo;t want to deal with something like &lt;code&gt;DigitalIndicator&amp;lt;ESP32C6OutputPin&amp;gt;(15)&lt;/code&gt; for now. This could also be handled by typaliasing, but I have some questions around how to best use Swift embedded with &lt;a href=&#34;https://docs.swift.org/embedded/documentation/embedded/existentials&#34;&gt;existentials&lt;/a&gt; &lt;a href=&#34;https://docs.swift.org/embedded/documentation/embedded/nonfinalgenericmethods&#34;&gt;and generics&lt;/a&gt; that I&amp;rsquo;d like to temporarily side step.&lt;/p&gt;
&lt;p&gt;This being a struct is a tad deceiving, It&amp;rsquo;s backed by C functions that point to specific hardware registers. In a Swift-all-the-way-down implementation I would maybe choose a &lt;code&gt;final Class&lt;/code&gt; or even an &lt;code&gt;Actor&lt;/code&gt; if that becomes a thing one could do?&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;MARK:&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt; OutputPin&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;OutputPin&lt;/span&gt;:GPIOPin {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;pinNumber&lt;/span&gt;:&lt;span style=&#34;color:#91d7e3&#34;&gt;UInt32&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;direction&lt;/span&gt;:GPIODirection = .output
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;setLevel&lt;/span&gt;(levelHigh:&lt;span style=&#34;color:#91d7e3&#34;&gt;Bool&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        gpio_set_level(gpio_num_t(&lt;span style=&#34;color:#91d7e3&#34;&gt;Int32&lt;/span&gt;(pinNumber)), levelHigh.asUInt32)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;setLevel&lt;/span&gt;(level:GPIOLevel) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        gpio_set_level(gpio_num_t(&lt;span style=&#34;color:#91d7e3&#34;&gt;Int32&lt;/span&gt;(pinNumber)), level.asUInt32)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//esp32C6 init&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;extension&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;OutputPin&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;init&lt;/span&gt;(pinNumber:&lt;span style=&#34;color:#91d7e3&#34;&gt;UInt32&lt;/span&gt;, activeLow:&lt;span style=&#34;color:#91d7e3&#34;&gt;Bool&lt;/span&gt; = &lt;span style=&#34;color:#f5a97f&#34;&gt;true&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//validate is GPIO output pin.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;ledPin&lt;/span&gt; = gpio_num_t(&lt;span style=&#34;color:#91d7e3&#34;&gt;Int32&lt;/span&gt;(pinNumber))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;.pinNumber = pinNumber
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;guard&lt;/span&gt; gpio_reset_pin(ledPin) == ESP_OK &lt;span style=&#34;color:#c6a0f6&#34;&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#91d7e3&#34;&gt;fatalError&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;cannot reset output pin &lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;pinNumber&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;guard&lt;/span&gt; gpio_set_direction(ledPin, &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;.direction.esp32C6) == ESP_OK &lt;span style=&#34;color:#c6a0f6&#34;&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#91d7e3&#34;&gt;fatalError&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;cannot reset output pin &lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;pinNumber&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;gpiopinswiftinputpin&#34;&gt;GPIOPin.swift:InputPin&lt;/h2&gt;
&lt;p&gt;ESP32C6 specific implementation, see notes above with OutputPin&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;InputPin&lt;/span&gt;:GPIOPin {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;pinNumber&lt;/span&gt;:&lt;span style=&#34;color:#91d7e3&#34;&gt;UInt32&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;direction&lt;/span&gt;:GPIODirection = .input
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//If the pad is not configured for input (or input and output) the returned value is always 0.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;readLevel&lt;/span&gt;() -&amp;gt; GPIOLevel {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        GPIOLevel(gpio_get_level(gpio_num_t(&lt;span style=&#34;color:#91d7e3&#34;&gt;Int32&lt;/span&gt;(pinNumber))))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;extension&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;InputPin&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;init&lt;/span&gt;(pinNumber:&lt;span style=&#34;color:#91d7e3&#34;&gt;UInt32&lt;/span&gt;, activeLow:&lt;span style=&#34;color:#91d7e3&#34;&gt;Bool&lt;/span&gt; = &lt;span style=&#34;color:#f5a97f&#34;&gt;true&lt;/span&gt;, useInternalHardware:&lt;span style=&#34;color:#91d7e3&#34;&gt;Bool&lt;/span&gt; = &lt;span style=&#34;color:#f5a97f&#34;&gt;true&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//validate is GPIO output pin.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;ledPin&lt;/span&gt; = gpio_num_t(&lt;span style=&#34;color:#91d7e3&#34;&gt;Int32&lt;/span&gt;(pinNumber))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;.pinNumber = pinNumber
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;guard&lt;/span&gt; gpio_reset_pin(ledPin) == ESP_OK &lt;span style=&#34;color:#c6a0f6&#34;&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#91d7e3&#34;&gt;fatalError&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;cannot reset output pin &lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;pinNumber&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;guard&lt;/span&gt; gpio_set_direction(ledPin, &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;.direction.esp32C6) == ESP_OK &lt;span style=&#34;color:#c6a0f6&#34;&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#91d7e3&#34;&gt;fatalError&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;cannot reset output pin &lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;pinNumber&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//validate pin has hardware &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; activeLow &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;amp;&amp;amp;&lt;/span&gt; useInternalHardware {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//use gpio_pull_mode_t&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            gpio_set_pull_mode(ledPin, GPIO_PULLUP_ONLY)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        } &lt;span style=&#34;color:#c6a0f6&#34;&gt;else&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;!&lt;/span&gt;activeLow &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;amp;&amp;amp;&lt;/span&gt; useInternalHardware {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            gpio_set_pull_mode(ledPin, GPIO_PULLDOWN_ONLY)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        } &lt;span style=&#34;color:#c6a0f6&#34;&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//could set with GPIO_FLOATING, but for now want to leave it as default&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;summary&#34;&gt;Summary&lt;/h2&gt;
&lt;p&gt;All of this was pretty easy once I got the the tooling issues sorted. The next batch, getting the WiFi working will require adding a C bridging component. I tried without but the WiFi library uses function like macros, and while there maybe a fancy work around, i&amp;rsquo;m just going to add a lib.&lt;/p&gt;
</description>
    </item>
    
    
    
    <item>
      <title>How does the espressif SDK handle wifi?</title>
      <link>https://whynotestflight.com/excuses/how-does-the-espressif-sdk-handle-wifi/</link>
      <pubDate>Sun, 07 Sep 2025 00:00:00 +0000</pubDate>
      
      <guid>https://whynotestflight.com/excuses/how-does-the-espressif-sdk-handle-wifi/</guid>
      <description>&lt;p&gt;Next step for me was to see if I could get any of the WiFi examples working. Which I did.  This post is definately more notes than a how-to.&lt;/p&gt;
&lt;p&gt;Here are the docs I used:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://docs.espressif.com/projects/esp-idf/en/v5.5.1/esp32c6/api-reference/network/index.html#wi-fi&#34;&gt;https://docs.espressif.com/projects/esp-idf/en/v5.5.1/esp32c6/api-reference/network/index.html#wi-fi&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-guides/wifi.html&#34;&gt;https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-guides/wifi.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://www.espressif.com/sites/default/files/documentation/esp32-c6_technical_reference_manual_en.pdf&#34;&gt;https://www.espressif.com/sites/default/files/documentation/esp32-c6_technical_reference_manual_en.pdf&lt;/a&gt; (search term(s): &amp;ldquo;modem&amp;rdquo;, &amp;ldquo;wifi&amp;rdquo;)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Here are the code examples I mainly looked at:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/espressif/esp-idf/tree/v5.5.1/examples/wifi/scan&#34;&gt;https://github.com/espressif/esp-idf/tree/v5.5.1/examples/wifi/scan&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/espressif/esp-idf/tree/v5.5.1/examples/wifi/getting_started/station&#34;&gt;https://github.com/espressif/esp-idf/tree/v5.5.1/examples/wifi/getting_started/station&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/espressif/esp-idf/blob/v5.5.1/examples/wifi/fast_scan/&#34;&gt;https://github.com/espressif/esp-idf/blob/v5.5.1/examples/wifi/fast_scan/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;(for station mode) &lt;a href=&#34;https://github.com/espressif/esp-idf/blob/v5.5.1/examples/wifi/power_save/&#34;&gt;https://github.com/espressif/esp-idf/blob/v5.5.1/examples/wifi/power_save/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/espressif/esp-idf/tree/v5.5.1/examples/protocols/http_request&#34;&gt;https://github.com/espressif/esp-idf/tree/v5.5.1/examples/protocols/http_request&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/espressif/esp-idf/blob/v5.5.1/examples/common_components/protocol_examples_common/wifi_connect.c&#34;&gt;https://github.com/espressif/esp-idf/blob/v5.5.1/examples/common_components/protocol_examples_common/wifi_connect.c&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/espressif/arduino-esp32/tree/master/libraries/WiFi/src&#34;&gt;https://github.com/espressif/arduino-esp32/tree/master/libraries/WiFi/src&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;what-are-the-different-modes&#34;&gt;What are the different modes?&lt;/h2&gt;
&lt;pre&gt;&lt;code&gt;- Station mode (aka STA mode or Wi-Fi client mode). ESP32 connects to an access point. 
- AP mode (aka Soft-AP mode or Access Point mode). Stations connect to the ESP32.
- Station/AP-coexistence mode (ESP32 is concurrently an access point and a station connected to another access point).
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&#34;what-was-it-like-running-the-different-examples&#34;&gt;What was it like running the different examples.&lt;/h2&gt;
&lt;p&gt;I followed the same pattern from the getting started, copying the folders and then running them.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-shell&#34; data-lang=&#34;shell&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;. &lt;span style=&#34;color:#f4dbd6&#34;&gt;$HOME&lt;/span&gt;/esp/esp-idf/export.sh
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;SOME_PORT&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt;/dev/&lt;span style=&#34;color:#c6a0f6&#34;&gt;$(&lt;/span&gt;ls /dev/ | grep cu.usbmodem&lt;span style=&#34;color:#c6a0f6&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#91d7e3&#34;&gt;cd&lt;/span&gt; ~/esp
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;cp -r &lt;span style=&#34;color:#f4dbd6&#34;&gt;$IDF_PATH&lt;/span&gt;/examples/wifi/scan wifi_scan
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#91d7e3&#34;&gt;cd&lt;/span&gt; wifi_scan
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;idf.py set-target esp32c6
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;idf.py menuconfig  &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# especially for the secon two&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;idf.py build &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# just to catch any build errors first&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;idf.py -p &lt;span style=&#34;color:#f4dbd6&#34;&gt;$SOME_PORT&lt;/span&gt; flash monitor
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;wifi-scan&#34;&gt;WiFi Scan&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/espressif/esp-idf/tree/v5.5.1/examples/wifi/scan&#34;&gt;https://github.com/espressif/esp-idf/tree/v5.5.1/examples/wifi/scan&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The scan sketch failed to run the first time I tried to build and flash it with the following error&amp;quot;&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;File &amp;#34;/Users/$MY_USER/.espressif/python_env/idf5.5_py3.13_env/lib/python3.13/site-packages/serial/serialposix.py&amp;#34;, line 517, in _reconfigure_port termios.tcsetattr( ~~~~~~~~~~~~~~~~~^ self.fd, ^^^^^^^^ termios.TCSANOW, ^^^^^^^^^^^^^^^^ [iflag, oflag, cflag, lflag, ispeed, ospeed, cc]) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ termios.error: (6, &amp;#39;Device not configured&amp;#39;)
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;But it worked again just fine when I re-ran it. No extra work on my part.&lt;/p&gt;
&lt;p&gt;I was not able to see many WiFI networks because I have not attached an &lt;a href=&#34;https://wiki.seeedstudio.com/xiao_esp32c6_getting_started/&#34;&gt;external antenna&lt;/a&gt; (search on page for antenna), but I could see my home one just fine.&lt;/p&gt;
&lt;p&gt;Also noted the introduction of &lt;a href=&#34;https://docs.espressif.com/projects/esp-idf/en/v5.5.1/esp32c6/api-reference/system/esp_err.html#c.ESP_ERROR_CHECK&#34;&gt;&lt;code&gt;ESP_ERROR_CHECK(someFunction);&lt;/code&gt;&lt;/a&gt; to catch &lt;a href=&#34;https://docs.espressif.com/projects/esp-idf/en/v5.5.1/esp32c6/api-reference/system/esp_err.html#_CPPv49esp_err_t&#34;&gt;&lt;code&gt;esp_err_t&lt;/code&gt;&lt;/a&gt; errors. These depend on an &lt;code&gt;esp_check.h&lt;/code&gt; include I don&amp;rsquo;t actually see in the header, so some other library must include it publicly, or it may even be in the base project include some how, although I did not find an explicit reference to it in &lt;a href=&#34;https://github.com/espressif/esp-idf/blob/release/v5.5/tools/cmake/project.cmake&#34;&gt;project.cmake&lt;/a&gt;, &lt;a href=&#34;https://github.com/espressif/esp-idf/blob/release/v5.5/tools/cmake/target.cmake&#34;&gt;target.cmake&lt;/a&gt; or &lt;a href=&#34;https://github.com/espressif/esp-idf/blob/release/v5.5/tools/cmake/idf.cmake&#34;&gt;idf.cmake&lt;/a&gt;.&lt;/p&gt;
&lt;h4 id=&#34;new-libraries&#34;&gt;New libraries&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&amp;ldquo;esp_wifi.h&amp;rdquo;: &lt;a href=&#34;https://docs.espressif.com/projects/esp-idf/en/v5.5.1/esp32c6/api-reference/network/esp_wifi.html&#34;&gt;Simple Wifi&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&amp;ldquo;esp_event.h&amp;rdquo;: &lt;a href=&#34;https://docs.espressif.com/projects/esp-idf/en/v5.5.1/esp32c6/api-reference/system/esp_event.html&#34;&gt;Event Loop Library&lt;/a&gt; &amp;ldquo;The event loop library allows components to declare events so that other components can register handlers &amp;ndash; codes that executes when those events occur. This allows loosely-coupled components to attach desired behavior to state changes of other components without application involvement&amp;hellip; One common case is, if a high-level library is using the Wi-Fi library: it may subscribe to ESP32 Wi-Fi Programming Model directly and act on those events.&amp;rdquo;&lt;/li&gt;
&lt;li&gt;&amp;ldquo;freertos/event_groups.h&amp;rdquo;: &lt;a href=&#34;https://www.freertos.org/Documentation/02-Kernel/04-API-references/12-Event-groups-or-flags/00-Event-groups&#34;&gt;Event Groups API&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&amp;ldquo;nvs_flash.h&amp;rdquo;: &lt;a href=&#34;https://docs.espressif.com/projects/esp-idf/en/v5.5.1/esp32c6/api-reference/storage/nvs_flash.html&#34;&gt;Non-Volatile Storage Library&lt;/a&gt; Handles remembering the WiFi Access Points found.&lt;/li&gt;
&lt;li&gt;&amp;ldquo;regex.h&amp;rdquo;: &lt;a href=&#34;https://www.man7.org/linux/man-pages/man3/regex.3.html&#34;&gt;C regex lib&lt;/a&gt; (current working directory over system headers) (Might be vestigial? Seems to build without it.)&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&#34;libraries-seen-before&#34;&gt;Libraries Seen Before&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&amp;ldquo;esp_log.h&amp;rdquo;: &lt;a href=&#34;https://docs.espressif.com/projects/esp-idf/en/v5.5.1/esp32c6/api-reference/system/log.html#_CPPv47esp_log16esp_log_config_tPKcPKcz&#34;&gt;Logging Library&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&amp;lt;string.h&amp;gt; : &lt;a href=&#34;https://man7.org/linux/man-pages/man3/string.3.html&#34;&gt;C String Library&lt;/a&gt; (system)&lt;/li&gt;
&lt;li&gt;&amp;ldquo;freertos/FreeRTOS.h&amp;rdquo; : &lt;a href=&#34;https://www.freertos.org&#34;&gt;FreeRTOS main&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&#34;not-explicitly-imported&#34;&gt;Not explicitly imported:&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://docs.espressif.com/projects/esp-idf/en/v5.5.1/esp32c6/api-reference/network/esp_netif.html&#34;&gt;https://docs.espressif.com/projects/esp-idf/en/v5.5.1/esp32c6/api-reference/network/esp_netif.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://docs.espressif.com/projects/esp-idf/en/v5.5.1/esp32c6/api-reference/system/esp_err.html&#34;&gt;https://docs.espressif.com/projects/esp-idf/en/v5.5.1/esp32c6/api-reference/system/esp_err.html&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&#34;other-useful-links&#34;&gt;Other useful links&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://docs.espressif.com/projects/esp-idf/en/v5.5.1/esp32c6/api-reference/network/esp_wifi.html#_CPPv416wifi_ap_record_t&#34;&gt;https://docs.espressif.com/projects/esp-idf/en/v5.5.1/esp32c6/api-reference/network/esp_wifi.html#_CPPv416wifi_ap_record_t&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The meat of the program is in &lt;code&gt;wifi_scan&lt;/code&gt;, which I include below, commented.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-C&#34; data-lang=&#34;C&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;void&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;wifi_scan&lt;/span&gt;(&lt;span style=&#34;color:#ed8796&#34;&gt;void&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//Initialize the TCP/IP stack and the event loop
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#8aadf4&#34;&gt;ESP_ERROR_CHECK&lt;/span&gt;(&lt;span style=&#34;color:#8aadf4&#34;&gt;esp_netif_init&lt;/span&gt;());
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#8aadf4&#34;&gt;ESP_ERROR_CHECK&lt;/span&gt;(&lt;span style=&#34;color:#8aadf4&#34;&gt;esp_event_loop_create_default&lt;/span&gt;());
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//Create the network interface handle and make sure it actually 
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//exists. 
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;esp_netif_t&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;*&lt;/span&gt;sta_netif &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;esp_netif_create_default_wifi_sta&lt;/span&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#8aadf4&#34;&gt;assert&lt;/span&gt;(sta_netif);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//initialize wifi with config
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;wifi_init_config_t&lt;/span&gt; cfg &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;WIFI_INIT_CONFIG_DEFAULT&lt;/span&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#8aadf4&#34;&gt;ESP_ERROR_CHECK&lt;/span&gt;(&lt;span style=&#34;color:#8aadf4&#34;&gt;esp_wifi_init&lt;/span&gt;(&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;amp;&lt;/span&gt;cfg));
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//Use the user settings to limit the number of networks reported
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//using the &amp;#34;access point info&amp;#34; type size to reserve the memory needed
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;uint16_t&lt;/span&gt; number &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; DEFAULT_SCAN_LIST_SIZE;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;wifi_ap_record_t&lt;/span&gt; ap_info[DEFAULT_SCAN_LIST_SIZE];
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;uint16_t&lt;/span&gt; ap_count &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;0&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#8aadf4&#34;&gt;memset&lt;/span&gt;(ap_info, &lt;span style=&#34;color:#f5a97f&#34;&gt;0&lt;/span&gt;, &lt;span style=&#34;color:#c6a0f6&#34;&gt;sizeof&lt;/span&gt;(ap_info));
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//use the Station Mode
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#8aadf4&#34;&gt;ESP_ERROR_CHECK&lt;/span&gt;(&lt;span style=&#34;color:#8aadf4&#34;&gt;esp_wifi_set_mode&lt;/span&gt;(WIFI_MODE_STA));
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//Start The Wifi
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#8aadf4&#34;&gt;ESP_ERROR_CHECK&lt;/span&gt;(&lt;span style=&#34;color:#8aadf4&#34;&gt;esp_wifi_start&lt;/span&gt;());
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//Optionally set up the scanning configuration to limit which channels to scan
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// and then DO THE SCAN
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#ifdef USE_CHANNEL_BITMAP
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;wifi_scan_config_t&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;*&lt;/span&gt;scan_config &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; (&lt;span style=&#34;color:#ed8796&#34;&gt;wifi_scan_config_t&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;*&lt;/span&gt;)&lt;span style=&#34;color:#8aadf4&#34;&gt;calloc&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;1&lt;/span&gt;,&lt;span style=&#34;color:#c6a0f6&#34;&gt;sizeof&lt;/span&gt;(&lt;span style=&#34;color:#ed8796&#34;&gt;wifi_scan_config_t&lt;/span&gt;));
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; (&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;!&lt;/span&gt;scan_config) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#8aadf4&#34;&gt;ESP_LOGE&lt;/span&gt;(TAG, &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Memory Allocation for scan config failed!&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#8aadf4&#34;&gt;array_2_channel_bitmap&lt;/span&gt;(channel_list, CHANNEL_LIST_SIZE, scan_config);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#8aadf4&#34;&gt;esp_wifi_scan_start&lt;/span&gt;(scan_config, &lt;span style=&#34;color:#91d7e3&#34;&gt;true&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#8aadf4&#34;&gt;free&lt;/span&gt;(scan_config);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#else
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#8aadf4&#34;&gt;esp_wifi_scan_start&lt;/span&gt;(&lt;span style=&#34;color:#91d7e3&#34;&gt;NULL&lt;/span&gt;, &lt;span style=&#34;color:#91d7e3&#34;&gt;true&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#endif &lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;/*USE_CHANNEL_BITMAP*/&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// Print out all the info based on that &amp;#34;access point info&amp;#34; type
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#8aadf4&#34;&gt;ESP_LOGI&lt;/span&gt;(TAG, &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Max AP number ap_info can hold = %u&amp;#34;&lt;/span&gt;, number);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#8aadf4&#34;&gt;ESP_ERROR_CHECK&lt;/span&gt;(&lt;span style=&#34;color:#8aadf4&#34;&gt;esp_wifi_scan_get_ap_num&lt;/span&gt;(&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;amp;&lt;/span&gt;ap_count));
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#8aadf4&#34;&gt;ESP_ERROR_CHECK&lt;/span&gt;(&lt;span style=&#34;color:#8aadf4&#34;&gt;esp_wifi_scan_get_ap_records&lt;/span&gt;(&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;amp;&lt;/span&gt;number, ap_info));
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#8aadf4&#34;&gt;ESP_LOGI&lt;/span&gt;(TAG, &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Total APs scanned = %u, actual AP number ap_info holds = %u&amp;#34;&lt;/span&gt;, ap_count, number);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;for&lt;/span&gt; (&lt;span style=&#34;color:#ed8796&#34;&gt;int&lt;/span&gt; i &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;0&lt;/span&gt;; i &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;lt;&lt;/span&gt; number; i&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;++&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#8aadf4&#34;&gt;ESP_LOGI&lt;/span&gt;(TAG, &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;SSID &lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\t\t&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;%s&amp;#34;&lt;/span&gt;, ap_info[i].ssid);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#8aadf4&#34;&gt;ESP_LOGI&lt;/span&gt;(TAG, &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;RSSI &lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\t\t&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;%d&amp;#34;&lt;/span&gt;, ap_info[i].rssi);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//defined and implemented station_example_main.c
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;        &lt;span style=&#34;color:#8aadf4&#34;&gt;print_auth_mode&lt;/span&gt;(ap_info[i].authmode);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; (ap_info[i].authmode &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;!=&lt;/span&gt; WIFI_AUTH_WEP) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//defined and implemented station_example_main.c
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;            &lt;span style=&#34;color:#8aadf4&#34;&gt;print_cipher_type&lt;/span&gt;(ap_info[i].pairwise_cipher, ap_info[i].group_cipher);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#8aadf4&#34;&gt;ESP_LOGI&lt;/span&gt;(TAG, &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Channel &lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\t\t&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;%d&amp;#34;&lt;/span&gt;, ap_info[i].primary);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;wifi-getting-started-station&#34;&gt;WiFi Getting Started Station&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/espressif/esp-idf/tree/v5.5.1/examples/wifi/getting_started/station&#34;&gt;https://github.com/espressif/esp-idf/tree/v5.5.1/examples/wifi/getting_started/station&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Similar to scan, but also handles a login. Also sets up for other &amp;ldquo;event types&amp;rdquo; going forward.&lt;/p&gt;
&lt;p&gt;Station Example also ran fine after menuconfig (not before). It includes teh &lt;a href=&#34;https://en.wikipedia.org/wiki/LwIP&#34;&gt;LwIP&lt;/a&gt; libraries, which I think are being used by the &lt;code&gt;IP_EVENT&lt;/code&gt; handler?&lt;/p&gt;
&lt;h4 id=&#34;new-includes&#34;&gt;New Includes&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&amp;ldquo;freertos/task.h&amp;rdquo; : &lt;a href=&#34;https://www.freertos.org/Documentation/02-Kernel/04-API-references/01-Task-creation/00-TaskHandle&#34;&gt;FreeRTOS TaskHandle&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&amp;ldquo;esp_system.h&amp;rdquo; : &lt;a href=&#34;https://docs.espressif.com/projects/esp-idf/en/v5.5.1/esp32c6/migration-guides/release-5.x/5.0/system.html#esp-system&#34;&gt;ESP System&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&amp;ldquo;lwip/err.h&amp;rdquo; : &lt;a href=&#34;https://savannah.nongnu.org/projects/lwip/&#34;&gt;Lightweight TCP/IP stack&lt;/a&gt;, &lt;a href=&#34;https://github.com/lwip-tcpip/lwip/blob/4599f551dead9eac233b91c0b9ee5879f5d0620a/src/include/lwip/err.h&#34;&gt;Errors&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&amp;ldquo;lwip/sys.h&amp;rdquo; :  &lt;a href=&#34;https://savannah.nongnu.org/projects/lwip/&#34;&gt;Lightweight TCP/IP stack&lt;/a&gt;, &lt;a href=&#34;https://github.com/lwip-tcpip/lwip/blob/4599f551dead9eac233b91c0b9ee5879f5d0620a/src/include/lwip/err.h&#34;&gt;Errors&lt;/a&gt; &lt;a href=&#34;https://github.com/lwip-tcpip/lwip/blob/4599f551dead9eac233b91c0b9ee5879f5d0620a/src/include/lwip/sys.h&#34;&gt;System&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&#34;seen-before&#34;&gt;Seen Before&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&amp;lt;string.h&amp;gt;&lt;/li&gt;
&lt;li&gt;&amp;ldquo;freertos/FreeRTOS.h&amp;rdquo;&lt;/li&gt;
&lt;li&gt;&amp;ldquo;freertos/event_groups.h&amp;rdquo;&lt;/li&gt;
&lt;li&gt;&amp;ldquo;esp_wifi.h&amp;rdquo;&lt;/li&gt;
&lt;li&gt;&amp;ldquo;esp_event.h&amp;rdquo;&lt;/li&gt;
&lt;li&gt;&amp;ldquo;esp_log.h&amp;rdquo;&lt;/li&gt;
&lt;li&gt;&amp;ldquo;nvs_flash.h&amp;rdquo;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The two main functions.  An event handler, and an initializer.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;event_handler&lt;/code&gt; is the handler given to the &lt;a href=&#34;https://docs.espressif.com/projects/esp-idf/en/v5.5.1/esp32c6/api-reference/system/esp_event.html#_CPPv435esp_event_handler_instance_register16esp_event_base_t7int32_t19esp_event_handler_tPvP28esp_event_handler_instance_t&#34;&gt;&lt;code&gt;esp_event_handler_instance_register&lt;/code&gt;&lt;/a&gt; in the start up.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;m unclear if Swift will play nice with this event handler.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-C&#34; data-lang=&#34;C&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;void&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;event_handler&lt;/span&gt;(&lt;span style=&#34;color:#ed8796&#34;&gt;void&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;*&lt;/span&gt; arg, &lt;span style=&#34;color:#ed8796&#34;&gt;esp_event_base_t&lt;/span&gt; event_base,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                                &lt;span style=&#34;color:#ed8796&#34;&gt;int32_t&lt;/span&gt; event_id, &lt;span style=&#34;color:#ed8796&#34;&gt;void&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;*&lt;/span&gt; event_data)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; (event_base &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;==&lt;/span&gt; WIFI_EVENT &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;amp;&amp;amp;&lt;/span&gt; event_id &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;==&lt;/span&gt; WIFI_EVENT_STA_START) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#8aadf4&#34;&gt;esp_wifi_connect&lt;/span&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    } &lt;span style=&#34;color:#c6a0f6&#34;&gt;else&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; (event_base &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;==&lt;/span&gt; WIFI_EVENT &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;amp;&amp;amp;&lt;/span&gt; event_id &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;==&lt;/span&gt; WIFI_EVENT_STA_DISCONNECTED) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; (s_retry_num &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;lt;&lt;/span&gt; EXAMPLE_ESP_MAXIMUM_RETRY) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#8aadf4&#34;&gt;esp_wifi_connect&lt;/span&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            s_retry_num&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;++&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#8aadf4&#34;&gt;ESP_LOGI&lt;/span&gt;(TAG, &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;retry to connect to the AP&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        } &lt;span style=&#34;color:#c6a0f6&#34;&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#8aadf4&#34;&gt;xEventGroupSetBits&lt;/span&gt;(s_wifi_event_group, WIFI_FAIL_BIT);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#8aadf4&#34;&gt;ESP_LOGI&lt;/span&gt;(TAG,&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;connect to the AP fail&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    } &lt;span style=&#34;color:#c6a0f6&#34;&gt;else&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; (event_base &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;==&lt;/span&gt; IP_EVENT &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;amp;&amp;amp;&lt;/span&gt; event_id &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;==&lt;/span&gt; IP_EVENT_STA_GOT_IP) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;ip_event_got_ip_t&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;*&lt;/span&gt; event &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; (&lt;span style=&#34;color:#ed8796&#34;&gt;ip_event_got_ip_t&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;*&lt;/span&gt;) event_data;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#8aadf4&#34;&gt;ESP_LOGI&lt;/span&gt;(TAG, &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;got ip:&amp;#34;&lt;/span&gt; IPSTR, &lt;span style=&#34;color:#8aadf4&#34;&gt;IP2STR&lt;/span&gt;(&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;amp;&lt;/span&gt;event&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;-&amp;gt;&lt;/span&gt;ip_info.ip));
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        s_retry_num &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;0&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#8aadf4&#34;&gt;xEventGroupSetBits&lt;/span&gt;(s_wifi_event_group, WIFI_CONNECTED_BIT);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;```&lt;/span&gt;C
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;void&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;wifi_init_sta&lt;/span&gt;(&lt;span style=&#34;color:#ed8796&#34;&gt;void&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    s_wifi_event_group &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;xEventGroupCreate&lt;/span&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#8aadf4&#34;&gt;ESP_ERROR_CHECK&lt;/span&gt;(&lt;span style=&#34;color:#8aadf4&#34;&gt;esp_netif_init&lt;/span&gt;());
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#8aadf4&#34;&gt;ESP_ERROR_CHECK&lt;/span&gt;(&lt;span style=&#34;color:#8aadf4&#34;&gt;esp_event_loop_create_default&lt;/span&gt;());
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#8aadf4&#34;&gt;esp_netif_create_default_wifi_sta&lt;/span&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;wifi_init_config_t&lt;/span&gt; cfg &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;WIFI_INIT_CONFIG_DEFAULT&lt;/span&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#8aadf4&#34;&gt;ESP_ERROR_CHECK&lt;/span&gt;(&lt;span style=&#34;color:#8aadf4&#34;&gt;esp_wifi_init&lt;/span&gt;(&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;amp;&lt;/span&gt;cfg));
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;esp_event_handler_instance_t&lt;/span&gt; instance_any_id;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;esp_event_handler_instance_t&lt;/span&gt; instance_got_ip;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#8aadf4&#34;&gt;ESP_ERROR_CHECK&lt;/span&gt;(&lt;span style=&#34;color:#8aadf4&#34;&gt;esp_event_handler_instance_register&lt;/span&gt;(WIFI_EVENT,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                                                        ESP_EVENT_ANY_ID,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                                                        &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;amp;&lt;/span&gt;event_handler,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                                                        &lt;span style=&#34;color:#91d7e3&#34;&gt;NULL&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                                                        &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;amp;&lt;/span&gt;instance_any_id));
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#8aadf4&#34;&gt;ESP_ERROR_CHECK&lt;/span&gt;(&lt;span style=&#34;color:#8aadf4&#34;&gt;esp_event_handler_instance_register&lt;/span&gt;(IP_EVENT,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                                                        IP_EVENT_STA_GOT_IP,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                                                        &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;amp;&lt;/span&gt;event_handler,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                                                        &lt;span style=&#34;color:#91d7e3&#34;&gt;NULL&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                                                        &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;amp;&lt;/span&gt;instance_got_ip));
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;wifi_config_t&lt;/span&gt; wifi_config &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        .sta &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            .ssid &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; EXAMPLE_ESP_WIFI_SSID,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            .password &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; EXAMPLE_ESP_WIFI_PASS,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;/* Authmode threshold resets to WPA2 as default if password matches WPA2 standards (password len =&amp;gt; 8).
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;             * If you want to connect the device to deprecated WEP/WPA networks, Please set the threshold value
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;             * to WIFI_AUTH_WEP/WIFI_AUTH_WPA_PSK and set the password with length and format matching to
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;             * WIFI_AUTH_WEP/WIFI_AUTH_WPA_PSK standards.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;             */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            .threshold.authmode &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; ESP_WIFI_SCAN_AUTH_MODE_THRESHOLD,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            .sae_pwe_h2e &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; ESP_WIFI_SAE_MODE,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            .sae_h2e_identifier &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; EXAMPLE_H2E_IDENTIFIER,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        },
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    };
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#8aadf4&#34;&gt;ESP_ERROR_CHECK&lt;/span&gt;(&lt;span style=&#34;color:#8aadf4&#34;&gt;esp_wifi_set_mode&lt;/span&gt;(WIFI_MODE_STA) );
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#8aadf4&#34;&gt;ESP_ERROR_CHECK&lt;/span&gt;(&lt;span style=&#34;color:#8aadf4&#34;&gt;esp_wifi_set_config&lt;/span&gt;(WIFI_IF_STA, &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;amp;&lt;/span&gt;wifi_config) );
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#8aadf4&#34;&gt;ESP_ERROR_CHECK&lt;/span&gt;(&lt;span style=&#34;color:#8aadf4&#34;&gt;esp_wifi_start&lt;/span&gt;() );
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#8aadf4&#34;&gt;ESP_LOGI&lt;/span&gt;(TAG, &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;wifi_init_sta finished.&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;/* Waiting until either the connection is established (WIFI_CONNECTED_BIT) or connection failed for the maximum
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;     * number of re-tries (WIFI_FAIL_BIT). The bits are set by event_handler() (see above) */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    EventBits_t bits &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;xEventGroupWaitBits&lt;/span&gt;(s_wifi_event_group,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            WIFI_CONNECTED_BIT &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;|&lt;/span&gt; WIFI_FAIL_BIT,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            pdFALSE,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            pdFALSE,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            portMAX_DELAY);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;/* xEventGroupWaitBits() returns the bits before the call returned, hence we can test which event actually
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;     * happened. */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; (bits &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;amp;&lt;/span&gt; WIFI_CONNECTED_BIT) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#8aadf4&#34;&gt;ESP_LOGI&lt;/span&gt;(TAG, &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;connected to ap SSID:%s password:%s&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                 EXAMPLE_ESP_WIFI_SSID, EXAMPLE_ESP_WIFI_PASS);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    } &lt;span style=&#34;color:#c6a0f6&#34;&gt;else&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; (bits &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;amp;&lt;/span&gt; WIFI_FAIL_BIT) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#8aadf4&#34;&gt;ESP_LOGI&lt;/span&gt;(TAG, &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Failed to connect to SSID:%s, password:%s&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                 EXAMPLE_ESP_WIFI_SSID, EXAMPLE_ESP_WIFI_PASS);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    } &lt;span style=&#34;color:#c6a0f6&#34;&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#8aadf4&#34;&gt;ESP_LOGE&lt;/span&gt;(TAG, &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;UNEXPECTED EVENT&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;wifi-http-request&#34;&gt;WiFi HTTP Request&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/espressif/esp-idf/tree/v5.5.1/examples/protocols/http_request&#34;&gt;https://github.com/espressif/esp-idf/tree/v5.5.1/examples/protocols/http_request&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&#34;new-libraries-1&#34;&gt;New Libraries&lt;/h4&gt;
&lt;p&gt;This minimal example just uses &lt;a href=&#34;https://en.wikipedia.org/wiki/LwIP&#34;&gt;lwip directly&lt;/a&gt;.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&amp;ldquo;lwip/err.h&amp;rdquo;&lt;/li&gt;
&lt;li&gt;&amp;ldquo;lwip/sockets.h&amp;rdquo;&lt;/li&gt;
&lt;li&gt;&amp;ldquo;lwip/sys.h&amp;rdquo;&lt;/li&gt;
&lt;li&gt;&amp;ldquo;lwip/netdb.h&amp;rdquo;&lt;/li&gt;
&lt;li&gt;&amp;ldquo;lwip/dns.h&amp;rdquo;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Note there is also a &lt;a href=&#34;https://github.com/espressif/esp-idf/tree/v5.5.1/examples/protocols/esp_http_client&#34;&gt;more complete http client example&lt;/a&gt; that uses an esp written &lt;a href=&#34;https://docs.espressif.com/projects/esp-idf/en/v5.5.1/esp32c6/api-reference/protocols/esp_http_client.html&#34;&gt;http client library&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;These examples use a dependency on &lt;a href=&#34;https://github.com/espressif/esp-idf/tree/v5.5.1/examples/common_components/protocol_examples_common&#34;&gt;protocol_examples_common&lt;/a&gt; found in the &lt;a href=&#34;https://github.com/espressif/esp-idf/blob/v5.5.1/examples/protocols/https_request/main/idf_component.yml&#34;&gt;idf_component.yml&lt;/a&gt;&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;${IDF_PATH}/examples/common_components/protocol_examples_common
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The &lt;a href=&#34;https://github.com/espressif/esp-idf/blob/fcae32885b0296b32044cb99ecbdc50d98dddb83/examples/common_components/protocol_examples_common/include/protocol_examples_common.h#L89&#34;&gt;example itself&lt;/a&gt; says its&amp;rsquo; not a good WiFi implementation.&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;/**
 * @brief Configure Wi-Fi or Ethernet, connect, wait for IP
 *
 * This all-in-one helper function is used in protocols examples to
 * reduce the amount of boilerplate in the example.
 *
 * It is not intended to be used in real world applications.
 * See examples under examples/wifi/getting_started/ and examples/ethernet/
 * for more complete Wi-Fi or Ethernet initialization code.
 *
 * Read &amp;#34;Establishing Wi-Fi or Ethernet Connection&amp;#34; section in
 * examples/protocols/README.md for more information about this function.
 *
 * @return ESP_OK on successful connection
 */
esp_err_t example_connect(void);

/**
 * Counterpart to example_connect, de-initializes Wi-Fi or Ethernet
 */
esp_err_t example_disconnect(void);
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Did look briefly into trying to make my own Wifi wrapper component:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://espressif-docs.readthedocs-hosted.com/projects/idf-component-manager/en/latest/guides/packaging_components.html&#34;&gt;https://espressif-docs.readthedocs-hosted.com/projects/idf-component-manager/en/latest/guides/packaging_components.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://docs.espressif.com/projects/esp-idf/en/stable/esp32/api-guides/build-system.html&#34;&gt;https://docs.espressif.com/projects/esp-idf/en/stable/esp32/api-guides/build-system.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://docs.espressif.com/projects/esp-idf/en/stable/esp32/api-guides/build-system.html#writing-pure-cmake-components&#34;&gt;https://docs.espressif.com/projects/esp-idf/en/stable/esp32/api-guides/build-system.html#writing-pure-cmake-components&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://docs.espressif.com/projects/esp-idf/en/v5.5.1/esp32c6/api-guides/c.html&#34;&gt;https://docs.espressif.com/projects/esp-idf/en/v5.5.1/esp32c6/api-guides/c.html&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;But decided to wait and see if I needed to do that to make WiFi in Swift work or not. I suspect I might, but not today.&lt;/p&gt;
&lt;h2 id=&#34;summary&#34;&gt;Summary&lt;/h2&gt;
&lt;p&gt;I have now seen the board do everything I plan for the Swift demo for Sketching this year using just the esp-idf tools.  Next step is to transfer this knowledge to Swift!&lt;/p&gt;
</description>
    </item>
    
    
    
    <item>
      <title>How does the espressif SDK handle inputs?</title>
      <link>https://whynotestflight.com/excuses/how-does-the-espressif-sdk-handle-inputs/</link>
      <pubDate>Sat, 06 Sep 2025 00:00:00 +0000</pubDate>
      
      <guid>https://whynotestflight.com/excuses/how-does-the-espressif-sdk-handle-inputs/</guid>
      <description>&lt;p&gt;So even though my target is writing as much as possible in Swift, my process will be to make things work in C first.&lt;/p&gt;
&lt;p&gt;The next simple step is to check how to add a digital input pin.&lt;/p&gt;
&lt;p&gt;Here are the docs I used:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://docs.espressif.com/projects/esp-idf/en/v5.5.1/esp32c6/api-reference/peripherals/gpio.html&#34;&gt;https://docs.espressif.com/projects/esp-idf/en/v5.5.1/esp32c6/api-reference/peripherals/gpio.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://www.espressif.com/sites/default/files/documentation/esp32-c6_technical_reference_manual_en.pdf#iomuxgpio&#34;&gt;https://www.espressif.com/sites/default/files/documentation/esp32-c6_technical_reference_manual_en.pdf#iomuxgpio&lt;/a&gt; (7.4.1)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Here are the examples I mainly looked at (not to be confused with the sleep examples in &lt;a href=&#34;https://openthread.io&#34;&gt;OpenThread&lt;/a&gt; &lt;a href=&#34;https://github.com/espressif/esp-idf/tree/v5.5.1/examples/openthread&#34;&gt;directory&lt;/a&gt;). Most of these inputs were interrupt enabled, which I will likely use later but did not in this example.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/espressif/esp-idf/tree/v5.5.1/examples/peripherals/gpio/generic_gpio&#34;&gt;https://github.com/espressif/esp-idf/tree/v5.5.1/examples/peripherals/gpio/generic_gpio&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/espressif/esp-idf/tree/v5.5.1/examples/system/light_sleep&#34;&gt;https://github.com/espressif/esp-idf/tree/v5.5.1/examples/system/light_sleep&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/espressif/esp-idf/tree/v5.5.1/examples/system/deep_sleep&#34;&gt;https://github.com/espressif/esp-idf/tree/v5.5.1/examples/system/deep_sleep&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This was the resulting project:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/carlynorama/esp32c6_tests/tree/add_button&#34;&gt;https://github.com/carlynorama/esp32c6_tests/tree/add_button&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;peculiarities-of-using-the-boot-button&#34;&gt;Peculiarities of Using the Boot Button&lt;/h2&gt;
&lt;p&gt;Adding a basic input button has pretty much the &lt;a href=&#34;https://www.whynotestflight.com/excuses/hello-led-on-an-avr-attiny45-in-c/&#34;&gt;same steps&lt;/a&gt; &lt;a href=&#34;https://www.whynotestflight.com/excuses/and-now-for-3-ways-to-set-an-internal-pullup/&#34;&gt;no matter the chip&lt;/a&gt;.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;the micro has to know the pin will be an input&lt;/li&gt;
&lt;li&gt;the micro has to know if internal hardware (pullups, pull downs) are being used&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Given chips and given pins on those chips might have some specialty behaviors, but those are the two biggies.&lt;/p&gt;
&lt;p&gt;On the ESP32-C6 GPIO 9 is one of the so-called &amp;ldquo;strapping&amp;rdquo; pins, pins that are associated with telling the micro what boot mode to be in.&lt;/p&gt;
&lt;p&gt;From the &lt;a href=&#34;https://www.espressif.com/sites/default/files/documentation/esp32-c6_technical_reference_manual_en.pdf&#34;&gt;technical reference manual&lt;/a&gt; (9.2.1) the default configuration of GPIO9 will be to have it&amp;rsquo;s internal pull up enabled.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;By default, GPIO9 is connected to the chip’s internal pull-up resistor. If GPIO9 is not connected or is
connected to an external high-impedance circuit, the internal weak pull-up determines the default input level
of this strapping pin (see Table 9.2-1).&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;The manual continues in section 9.2.2:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The values of GPIO8 and GPIO9 at reset determine the boot mode after the reset is released. Table 9.2-2 shows the strapping pin values of GPIO8 and GPIO9, and the associated boot modes. (x: this value is ignored.)&lt;/p&gt;&lt;/blockquote&gt;
&lt;table&gt;
  &lt;thead&gt;
      &lt;tr&gt;
          &lt;th style=&#34;text-align: left&#34;&gt;Boot Mode&lt;/th&gt;
          &lt;th style=&#34;text-align: center&#34;&gt;GPIO9&lt;/th&gt;
          &lt;th style=&#34;text-align: center&#34;&gt;GPIO8&lt;/th&gt;
      &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
      &lt;tr&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;SPI Boot&lt;/td&gt;
          &lt;td style=&#34;text-align: center&#34;&gt;1&lt;/td&gt;
          &lt;td style=&#34;text-align: center&#34;&gt;x&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;Download Boot&lt;/td&gt;
          &lt;td style=&#34;text-align: center&#34;&gt;0&lt;/td&gt;
          &lt;td style=&#34;text-align: center&#34;&gt;1&lt;/td&gt;
      &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;We can see on the &lt;a href=&#34;https://files.seeedstudio.com/wiki/SeeedStudio-XIAO-ESP32C6/XIAO-ESP32-C6_v1.0_SCH_PDF_24028.pdf&#34;&gt;Xiao&amp;rsquo;s schematic&lt;/a&gt; (labeled net BOOT)that Seeed has attached the appropriate active low switch so that GPIO9 stays high by default.&lt;/p&gt;
&lt;p&gt;This all means that when using pin 9 failing to set the internal pull up resistor won&amp;rsquo;t be a big deal because it will be set for us. It also means that the boot switch must be active low if we don&amp;rsquo;t want to change the expected default boot behaviors.&lt;/p&gt;
&lt;p&gt;The ESP32-C6 SDK offers a handy command &lt;a href=&#34;https://docs.espressif.com/projects/esp-idf/en/latest/esp32c6/api-reference/peripherals/gpio.html#_CPPv426gpio_dump_io_configurationP4FILE8uint64_t&#34;&gt;&lt;code&gt;gpio_dump_io_configuration&lt;/code&gt;&lt;/a&gt; to print out the current pin, as discussed in the &lt;a href=&#34;https://docs.espressif.com/projects/esp-idf/en/latest/esp32c6/api-reference/peripherals/gpio.html#check-current-configuration-of-ios&#34;&gt;API reference&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;It looks like:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;================IO DUMP Start================
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;IO[9] -
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  Pullup: 1, Pulldown: 0, DriveCap: 2
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  InputEn: 1, OutputEn: 0, OpenDrain: 0
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  FuncSel: 0 (IOMUX)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  SleepSelEn: 1
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;IO[15] -
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  Pullup: 1, Pulldown: 0, DriveCap: 2
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  InputEn: 0, OutputEn: 1, OpenDrain: 0
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  FuncSel: 1 (GPIO)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  GPIO Matrix SigOut ID: 128 (simple GPIO output)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  SleepSelEn: 1
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;=================IO DUMP End=================
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;example-code&#34;&gt;Example Code&lt;/h2&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-C&#34; data-lang=&#34;C&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// Needed for logging to serial monitor
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// with TAG prefix
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#include&lt;/span&gt; &lt;span style=&#34;color:#6e738d;font-weight:bold;font-style:italic&#34;&gt;&amp;lt;stdio.h&amp;gt;&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#include&lt;/span&gt; &lt;span style=&#34;color:#6e738d;font-weight:bold;font-style:italic&#34;&gt;&amp;#34;esp_log.h&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// Needed for portTICK_PERIOD_MS
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#include&lt;/span&gt; &lt;span style=&#34;color:#6e738d;font-weight:bold;font-style:italic&#34;&gt;&amp;#34;freertos/FreeRTOS.h&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#include&lt;/span&gt; &lt;span style=&#34;color:#6e738d;font-weight:bold;font-style:italic&#34;&gt;&amp;#34;freertos/task.h&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// Needed for io pins
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#include&lt;/span&gt; &lt;span style=&#34;color:#6e738d;font-weight:bold;font-style:italic&#34;&gt;&amp;#34;driver/gpio.h&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// Blinking related defines
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#define BLINK_GPIO          15
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#define BLINK_PERIOD_SLOW   2000
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#define BLINK_PERIOD_FAST   500
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// Button related defines
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#define BOOT_BUTTON_NUM     9
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#define MY_BUTTON_NUM BOOT_BUTTON_NUM
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// active low
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#define MY_BUTTON_PRESSED_STATE 0
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// logging prefix
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;const&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;char&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;*&lt;/span&gt;TAG &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;simple_button&amp;#34;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// current state of the LED
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;uint8_t&lt;/span&gt; s_led_state &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;0&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//current blink period
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;uint32_t&lt;/span&gt; current_blink_period &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; BLINK_PERIOD_SLOW;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//----------- LED
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;void&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;configure_led&lt;/span&gt;(&lt;span style=&#34;color:#ed8796&#34;&gt;void&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#8aadf4&#34;&gt;ESP_LOGI&lt;/span&gt;(TAG, &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Example configured to blink GPIO LED!&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#8aadf4&#34;&gt;gpio_reset_pin&lt;/span&gt;(BLINK_GPIO);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#8aadf4&#34;&gt;gpio_set_direction&lt;/span&gt;(BLINK_GPIO, GPIO_MODE_OUTPUT);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;void&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;blink_led&lt;/span&gt;(&lt;span style=&#34;color:#ed8796&#34;&gt;void&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;/* Set the GPIO level according to the state (LOW or HIGH)*/&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#8aadf4&#34;&gt;gpio_set_level&lt;/span&gt;(BLINK_GPIO, s_led_state);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//----------- Button
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;void&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;configure_button&lt;/span&gt;(&lt;span style=&#34;color:#ed8796&#34;&gt;void&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#8aadf4&#34;&gt;gpio_set_direction&lt;/span&gt;(MY_BUTTON_NUM, GPIO_MODE_INPUT);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//??? No need to set internal pulls? 
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// will return 1 when the button read matches the value expected for a 
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// pressed button. 
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;uint8_t&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;read_button&lt;/span&gt;(){
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; (&lt;span style=&#34;color:#8aadf4&#34;&gt;gpio_get_level&lt;/span&gt;(MY_BUTTON_NUM) &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;==&lt;/span&gt; MY_BUTTON_PRESSED_STATE);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//----------- Configure Info 
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;void&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;reveal_configuration&lt;/span&gt;(&lt;span style=&#34;color:#ed8796&#34;&gt;void&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//shows all
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//gpio_dump_io_configuration(stdout, SOC_GPIO_VALID_GPIO_MASK);
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#8aadf4&#34;&gt;gpio_dump_io_configuration&lt;/span&gt;(stdout, (&lt;span style=&#34;color:#f5a97f&#34;&gt;1ULL&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;lt;&amp;lt;&lt;/span&gt; BLINK_GPIO) &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;|&lt;/span&gt; (&lt;span style=&#34;color:#f5a97f&#34;&gt;1ULL&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;lt;&amp;lt;&lt;/span&gt; BOOT_BUTTON_NUM));
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;void&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;app_main&lt;/span&gt;(&lt;span style=&#34;color:#ed8796&#34;&gt;void&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// Configure the peripherals
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#8aadf4&#34;&gt;configure_led&lt;/span&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#8aadf4&#34;&gt;configure_button&lt;/span&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//print out the information
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#8aadf4&#34;&gt;reveal_configuration&lt;/span&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;while&lt;/span&gt; (&lt;span style=&#34;color:#f5a97f&#34;&gt;1&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// pin HIGH is __LED OFF__ for the XIAO built in LED. 
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;        &lt;span style=&#34;color:#8aadf4&#34;&gt;ESP_LOGI&lt;/span&gt;(TAG, &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Turning the LED %s!&amp;#34;&lt;/span&gt;, s_led_state &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;==&lt;/span&gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;true&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;?&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;OFF&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;ON&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#8aadf4&#34;&gt;blink_led&lt;/span&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;/* Toggle the LED state */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        s_led_state &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;!&lt;/span&gt;s_led_state;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// if button is true, blink fast, else blink slow
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; (&lt;span style=&#34;color:#8aadf4&#34;&gt;read_button&lt;/span&gt;() &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;==&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;1&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            current_blink_period &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; BLINK_PERIOD_FAST;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        } &lt;span style=&#34;color:#c6a0f6&#34;&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            current_blink_period &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; BLINK_PERIOD_SLOW;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#8aadf4&#34;&gt;vTaskDelay&lt;/span&gt;(current_blink_period &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;/&lt;/span&gt; portTICK_PERIOD_MS);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;summary&#34;&gt;Summary&lt;/h2&gt;
&lt;p&gt;That&amp;rsquo;s enough for one round. Next step is to confirm I can make the WiFi work with just the SDK as well.&lt;/p&gt;
</description>
    </item>
    
    
    
    <item>
      <title>Can I program an ESP32C6 with the Swift example code?</title>
      <link>https://whynotestflight.com/excuses/can-i-program-an-esp32c6-with-the-swift-example-code/</link>
      <pubDate>Fri, 05 Sep 2025 00:00:00 +0000</pubDate>
      
      <guid>https://whynotestflight.com/excuses/can-i-program-an-esp32c6-with-the-swift-example-code/</guid>
      <description>&lt;p&gt;So the crazy thing is how much easier this process was than last year getting Swift up and &lt;a href=&#34;https://forums.swift.org/t/example-pico-w-code-works-on-supercon-badge/75769&#34;&gt;running on the picow&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Between the improved SwiftLang &lt;a href=&#34;https://docs.swift.org/embedded/documentation/embedded/&#34;&gt;embedded docs&lt;/a&gt; and &lt;a href=&#34;https://github.com/swiftlang/swift-embedded-examples&#34;&gt;example repo&lt;/a&gt;, &lt;a href=&#34;https://www.swift.org/swiftly/documentation/swiftlydocs/&#34;&gt;Swiftly&lt;/a&gt; being available on the Mac, &lt;a href=&#34;https://developer.espressif.com/tags/swift/&#34;&gt;espressif support&lt;/a&gt;&amp;hellip; a comparative cake walk. Seeed also gives a shout out on how to use &lt;a href=&#34;https://wiki.seeedstudio.com/xiao-esp32-swift/&#34;&gt;Swift with this exact board&lt;/a&gt;, but its docs are little behind. Not because they&amp;rsquo;re slow to update, just because things have moved that fast.&lt;/p&gt;
&lt;h2 id=&#34;run-an-example&#34;&gt;Run an Example&lt;/h2&gt;
&lt;p&gt;It is still recommended to use a development chain which is now easy to get with &lt;a href=&#34;https://www.whynotestflight.com/tags/swiftly/&#34;&gt;Swiftly&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The below are the commands only from &lt;a href=&#34;https://developer.espressif.com/blog/build-embedded-swift-application-for-esp32c6/&#34;&gt;a article from espressif&lt;/a&gt; with only a couple of tweaks, it assumes there is a &lt;a href=&#34;https://whynotestflight.com/excuses/can-i-program-a-an-esp32c6-with-the-esp-idf/&#34;&gt;working esp-idf installed&lt;/a&gt;, but that hasn&amp;rsquo;t already been loaded into the shell.&lt;/p&gt;
&lt;p&gt;Also, provided in that article is &lt;a href=&#34;https://wokwi.com/experimental/viewer?diagram=https://raw.githubusercontent.com/georgik/swift-embedded-examples/feature/wokwi/esp32-led-blink-sdk/diagram.json&amp;amp;firmware=https://github.com/georgik/swift-embedded-examples/releases/download/v0.1/embedded-swift-esp32-c6-led-blink-sdk.uf2.bin&#34;&gt;a Wokwi demo&lt;/a&gt;, which is a very very nice touch!&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-shell&#34; data-lang=&#34;shell&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## Locate the esp-idf install, if haven&amp;#39;t added alias to shell&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## assumes it lives in user root. &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;. &lt;span style=&#34;color:#f4dbd6&#34;&gt;$HOME&lt;/span&gt;/esp/esp-idf/export.sh
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# brew install swiftly&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## Install Swift 6.2 development snapshot and switch to it when done&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;swiftly install --use 6.2-snapshot 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## put this where you want it:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;git clone https://github.com/swiftlang/swift-embedded-examples.git --single-branch --branch main
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## change into example folder&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#91d7e3&#34;&gt;cd&lt;/span&gt; swift-embedded-examples/esp32-led-strip-sdk
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## set the target for the project&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;idf.py set-target esp32c6
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## build and run&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;idf.py build flash monitor
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# Use Ctrl+] to quit the monitor application.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;For me it just worked! Whew! That was nice!&lt;/p&gt;
&lt;h3 id=&#34;optional-environment-improvement-add-alias-for-esp-idf&#34;&gt;Optional Environment Improvement, add alias for esp-idf&lt;/h3&gt;
&lt;p&gt;Consider adding an alias to make loading in the location of the esp-idf tools easier. &lt;a href=&#34;https://docs.espressif.com/projects/esp-idf/en/stable/esp32/get-started/linux-macos-setup.html#step-4-set-up-the-environment-variables&#34;&gt;from the docs&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Copy and paste the following command to your shell&amp;rsquo;s profile (.profile, .bashrc, .zprofile, etc.)&lt;/p&gt;&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;alias get_idf=&#39;. $HOME/esp/esp-idf/export.sh&#39;&lt;/code&gt;&lt;/p&gt;&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;Refresh the configuration by restarting the terminal session or by running &lt;code&gt;source [path to profile]&lt;/code&gt;, for example, &lt;code&gt;source ~/.bashrc&lt;/code&gt;.
Now you can run get_idf to set up or refresh the esp-idf environment in any terminal session.&lt;/p&gt;&lt;/blockquote&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;
## Summary

So there are two things on deck for me next

A. get a switch working
B. reorganize the code

And I&amp;#39;m not sure which one I&amp;#39;m going to prioritize so I&amp;#39;ll save it for the next post. 
&lt;/code&gt;&lt;/pre&gt;</description>
    </item>
    
    
    
    <item>
      <title>Can I program a an ESP32C6 with the esp-idf?</title>
      <link>https://whynotestflight.com/excuses/can-i-program-a-an-esp32c6-with-the-esp-idf/</link>
      <pubDate>Thu, 04 Sep 2025 00:00:00 +0000</pubDate>
      
      <guid>https://whynotestflight.com/excuses/can-i-program-a-an-esp32c6-with-the-esp-idf/</guid>
      <description>&lt;p&gt;So to go along with the server I want to have an object that talks to it. Which means one with a stable WiFi chip. Very popular right now is &lt;a href=&#34;https://www.espressif.com&#34;&gt;espressif&lt;/a&gt;&amp;rsquo;s &lt;a href=&#34;https://documentation.espressif.com/esp32-c6_datasheet_en.html&#34;&gt;ESP32-C6&lt;/a&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The ESP32-C6 SoC (System on Chip) supports Wi-Fi 6 in 2.4 GHz band, Bluetooth 5, Zigbee 3.0 and Thread1.3. It consists of a high-performance (HP) 32-bit RISC-V processor, an low-power (LP) 32-bit RISC-V processor,wireless baseband and MAC (Wi-Fi, Bluetooth LE, and 802.15.4), RF module, and numerous peripherals. Wi-Fi,Bluetooth and 802.15.4 coexist with each other and share the same antenna.&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;I was interested in trying out a &lt;a href=&#34;https://en.wikipedia.org/wiki/RISC-V&#34;&gt;RISC-V&lt;/a&gt; chip since I hadn&amp;rsquo;t played with one of those before.&lt;/p&gt;
&lt;p&gt;Seeed Studio&amp;rsquo;s &lt;a href=&#34;https://wiki.seeedstudio.com/xiao_esp32c6_getting_started/&#34;&gt;XIAO ESP32C6&lt;/a&gt; won out as the dev board, honestly because todbot collects boards that have the same form factor as &lt;a href=&#34;https://www.adafruit.com/search?q=Adafruit+QT+py&#34;&gt;Adafruit&amp;rsquo;s QT Py&lt;/a&gt; and he had an extra. Also its small size is perfect for my target project.&lt;/p&gt;
&lt;p&gt;Other ESP32-C6 dev boards include (info links, not purchase links):&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://docs.espressif.com/projects/esp-dev-kits/en/latest/esp32c6/esp32-c6-devkitm-1/user_guide.html&#34;&gt;Official Dev Kit&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://www.waveshare.com/esp32-c6-touch-lcd-1.47.htm&#34;&gt;Waveshare ESP32-C6 1.47inch Touch Display Development Board&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;about-the-board&#34;&gt;About the Board&lt;/h2&gt;
&lt;p&gt;The XIAO ESP3232C6 board is tiny, but it packs A LOT in.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://wiki.seeedstudio.com/xiao_esp32c6_getting_started/&#34;&gt;https://wiki.seeedstudio.com/xiao_esp32c6_getting_started/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src=&#34;block_dia.png&#34; alt=&#34;block diagram showing location of leds, buttons and antenna mount&#34;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;pin_dia.png&#34; alt=&#34;pin diagram&#34;&gt;&lt;/p&gt;
&lt;p&gt;Of the two led&amp;rsquo;s on the board one is the classic &amp;ldquo;built in led&amp;rdquo; to blink hello world to, and the other is hooked into the battery management system. Hopefully I&amp;rsquo;ll get back to that later.&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;The red light behavior for the XIAO ESP32C6 is as follows:

When no battery is connected:
The red light turns on when the Type-C cable is connected and turns off after 30 seconds.
When a battery is connected and the Type-C cable is plugged in for charging:
The red light flashes.
When the battery is fully charged via the Type-C connection:
The red light turns off.
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The two buttons are the reset button and the boot button.&lt;/p&gt;
&lt;p&gt;While the boot button is &lt;em&gt;tiny&lt;/em&gt; I&amp;rsquo;m hoping later in the project I should be able to find a toothpick or something to temporarily hijack it for hello worlding a button.&lt;/p&gt;
&lt;h2 id=&#34;board-proof-of-life&#34;&gt;Board Proof of Life&lt;/h2&gt;
&lt;p&gt;It&amp;rsquo;s fairly rare these days to get a dud board, but it&amp;rsquo;s best to make sure the board actually works with familiar tooling before launching into unfamiliar tooling.&lt;/p&gt;
&lt;p&gt;Seeed actually provides &lt;a href=&#34;https://wiki.seeedstudio.com/xiao_esp32c6_getting_started/#software-preparation&#34;&gt;step by step instructions&lt;/a&gt; with screen shots on how to get things set up in the Arduino IDE, an environment I know well.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Quick link to the board profile if you know your way around: &lt;a href=&#34;https://github.com/espressif/arduino-esp32&#34;&gt;https://github.com/espressif/arduino-esp32&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;change-the-blink-sketch-to-uneven&#34;&gt;Change the blink sketch to uneven&lt;/h3&gt;
&lt;p&gt;One of the things I do with the example blink sketch is change the the blink patter to be uneven.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-C&#34; data-lang=&#34;C&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// the setup function runs once when you press reset or power the board
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;void&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;setup&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// initialize digital pin LED_BUILTIN as an output.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;  &lt;span style=&#34;color:#8aadf4&#34;&gt;pinMode&lt;/span&gt;(LED_BUILTIN, OUTPUT);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// the loop function runs over and over again forever
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;void&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;loop&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#8aadf4&#34;&gt;digitalWrite&lt;/span&gt;(LED_BUILTIN, HIGH);  &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// turn the LED on (HIGH is the voltage level)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;  &lt;span style=&#34;color:#8aadf4&#34;&gt;delay&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;500&lt;/span&gt;);                      &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// wait for a second
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;  &lt;span style=&#34;color:#8aadf4&#34;&gt;digitalWrite&lt;/span&gt;(LED_BUILTIN, LOW);   &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// turn the LED off by making the voltage LOW
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;  &lt;span style=&#34;color:#8aadf4&#34;&gt;delay&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;2000&lt;/span&gt;);                      &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// wait for a second
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;On the Xiao, this code will have the LED be &lt;strong&gt;ON&lt;/strong&gt; for longer than OFF because the LED&amp;rsquo;s current is being sinked by the pin, rather than sourced from the pin. This is more the norm in production electronics vs hobby electronics &lt;a href=&#34;(https://electronics.stackexchange.com/questions/332/current-sourcing-current-sinking)&#34;&gt;more&lt;/a&gt;.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;See the The &amp;ldquo;GPIO15&amp;rdquo; labeled net on the schematic (big red X means not populated): &lt;a href=&#34;https://files.seeedstudio.com/wiki/SeeedStudio-XIAO-ESP32C6/XIAO-ESP32-C6_v1.0_SCH_PDF_24028.pdf&#34;&gt;https://files.seeedstudio.com/wiki/SeeedStudio-XIAO-ESP32C6/XIAO-ESP32-C6_v1.0_SCH_PDF_24028.pdf&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Where pin 15 is declared as the builtin in the code: &lt;a href=&#34;https://github.com/espressif/arduino-esp32/blob/561136870b4308d9deb942461e63e42c788546f3/variants/XIAO_ESP32C6/pins_arduino.h#L13&#34;&gt;https://github.com/espressif/arduino-esp32/blob/561136870b4308d9deb942461e63e42c788546f3/variants/XIAO_ESP32C6/pins_arduino.h#L13&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;install-official-tools&#34;&gt;Install Official Tools&lt;/h2&gt;
&lt;p&gt;Espressif wraps its SDK in a pretty robust set of tools (Integrated Development Framework), for which they&amp;rsquo;ve written very explicit install instructions:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://docs.espressif.com/projects/esp-idf/en/v5.5.1/esp32c6/get-started/linux-macos-setup.html&#34;&gt;https://docs.espressif.com/projects/esp-idf/en/v5.5.1/esp32c6/get-started/linux-macos-setup.html&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Here&amp;rsquo;s a summary, but I suggest reading the full page, &lt;em&gt;making sure its actually about the target you&amp;rsquo;re looking for&lt;/em&gt;. (i.e. the url says &lt;code&gt;esp32c6&lt;/code&gt; NOT simply &lt;code&gt;esp32&lt;/code&gt;. &lt;code&gt;esp32&lt;/code&gt; is actually a different family than &lt;code&gt;esp32c6&lt;/code&gt; and its tooling won&amp;rsquo;t work!)&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-shell&#34; data-lang=&#34;shell&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## required&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;brew install cmake ninja dfu-util
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## recommended&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;brew install ccache
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Had:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://cmake.org&#34;&gt;https://cmake.org&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://ninja-build.org&#34;&gt;https://ninja-build.org&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;New:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://dfu-util.sourceforge.net&#34;&gt;https://dfu-util.sourceforge.net&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;dfu-util is a host side implementation of the DFU 1.0 and DFU 1.1 specifications of the USB forum. DFU is intended to download and upload firmware to/from devices connected over USB.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://ccache.dev&#34;&gt;https://ccache.dev&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;Ccache is a compiler cache. It speeds up recompilation by caching previous compilations and detecting when the same compilation is being done again.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Note, ccache posted a fairly ominous warning&amp;hellip; maybe I will start using containers more&amp;hellip;&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;To install symlinks for compilers that will automatically use
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ccache, prepend this directory to your PATH:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  /opt/homebrew/opt/ccache/libexec
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;If this is an upgrade and you have previously added the symlinks to
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;your PATH, you may need to modify it to the path specified above so
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;it points to the current version.
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;NOTE: ccache can prevent some software from compiling.
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ALSO NOTE: The brew command, by design, will never use ccache.
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;So espressif wants you to put their tooling at the root of the user, but does provide instruction on &lt;a href=&#34;https://docs.espressif.com/projects/esp-idf/en/stable/esp32/get-started/linux-macos-setup.html#customizing-the-tools-installation-path&#34;&gt;how to map to somewhere else&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Also, there is a &lt;a href=&#34;https://docs.espressif.com/projects/vscode-esp-idf-extension/en/latest/&#34;&gt;VSCode plugin&lt;/a&gt; that will do this all for you, but I find VSCode tooling very aggressive and prefer custom scripts that don&amp;rsquo;t start automagically doing things I didn&amp;rsquo;t ask to be done. I also don&amp;rsquo;t enjoy vendor lock in. I also find doing these things myself helps with trouble shooting later. YMMV.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-shell&#34; data-lang=&#34;shell&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;mkdir -p ~/esp 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#91d7e3&#34;&gt;cd&lt;/span&gt; ~/esp
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;git clone -b v5.5.1 --recursive https://github.com/espressif/esp-idf.git
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## Install the tools&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#91d7e3&#34;&gt;cd&lt;/span&gt; ~/esp/esp-idf
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;./install.sh esp32c6 &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#note NOT esp32, esp32c6 &amp;lt;---- !!!!!&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;hello-world-with-official-tools&#34;&gt;Hello World with Official Tools&lt;/h2&gt;
&lt;p&gt;&lt;a href=&#34;https://docs.espressif.com/projects/esp-idf/en/stable/esp32/get-started/linux-macos-setup.html#step-4-set-up-the-environment-variables&#34;&gt;https://docs.espressif.com/projects/esp-idf/en/stable/esp32/get-started/linux-macos-setup.html#step-4-set-up-the-environment-variables&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;In the terminal window that will be the shell doing the building and running:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-shell&#34; data-lang=&#34;shell&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## Set up the environment variables&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;. &lt;span style=&#34;color:#f4dbd6&#34;&gt;$HOME&lt;/span&gt;/esp/esp-idf/export.sh
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## Go to the dev folder&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#91d7e3&#34;&gt;cd&lt;/span&gt; ~/esp
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## pull out the example&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;cp -r &lt;span style=&#34;color:#f4dbd6&#34;&gt;$IDF_PATH&lt;/span&gt;/examples/get-started/hello_world .
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## linux&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# ls /dev/ | grep tty&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## macOS &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ls /dev/ | grep cu. &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## or ls /dev/cu.*&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Mine was called /dev/cu.usbmodem2101, plug into a different port, it will change.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-shell&#34; data-lang=&#34;shell&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## SPECIFIC TO MINE&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;SOME_PORT&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt;/dev/cu.usbmodem2101
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#91d7e3&#34;&gt;cd&lt;/span&gt; ~/esp/hello_world
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;idf.py set-target esp32c6
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# this creates sdkconfig, look at it&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;cat sdkconfig
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## optional/not needed for hello world. THe below edits sdkconfig &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## with verification to help prevent errors&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# idf.py menuconfig &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;idf.py build
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;idf.py -p &lt;span style=&#34;color:#f4dbd6&#34;&gt;$SOME_PORT&lt;/span&gt; flash
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-shell&#34; data-lang=&#34;shell&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# assumes 40 MHz, use idf.py menuconfig to change if needed&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;idf.py -p &lt;span style=&#34;color:#f4dbd6&#34;&gt;$SOME_PORT&lt;/span&gt; monitor
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# CNTRL+] to leave&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;blink-with-official-tools&#34;&gt;blink with official tools&lt;/h2&gt;
&lt;p&gt;The hello world example doesn&amp;rsquo;t touch the GPIO which, so on to &lt;code&gt;blink&lt;/code&gt;.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/espressif/esp-idf/blob/v5.5.1/examples/get-started/blink/README.md&#34;&gt;https://github.com/espressif/esp-idf/blob/v5.5.1/examples/get-started/blink/README.md&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If in a totally new Terminal window&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-shell&#34; data-lang=&#34;shell&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;. &lt;span style=&#34;color:#f4dbd6&#34;&gt;$HOME&lt;/span&gt;/esp/esp-idf/export.sh
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ls /dev/ | grep cu. &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## or ls /dev/cu.*&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;SOME_PORT&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; dev.cu.someusbmodem
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Pull out the blink example code and go&amp;hellip;&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-shell&#34; data-lang=&#34;shell&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## or where ever you want to store your files&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#91d7e3&#34;&gt;cd&lt;/span&gt; ~/esp
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;cp -r &lt;span style=&#34;color:#f4dbd6&#34;&gt;$IDF_PATH&lt;/span&gt;/examples/get-started/blink .
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## Set the GPIO_BLINK pin to 15 here&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#91d7e3&#34;&gt;cd&lt;/span&gt; blink
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# this is PER PROJECT, do it in the project folder. &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;idf.py set-target esp32c6
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## MUST change Example Configuration. It&amp;#39;s not an LED strip, GPIO pin (needs to be 15), etc. &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;idf.py menuconfig
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;idf.py build
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## do it on one this time&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;idf.py -p &lt;span style=&#34;color:#f4dbd6&#34;&gt;$SOME_PORT&lt;/span&gt; flash monitor
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Also went fairly smoothly and easily. Yet I don&amp;rsquo;t know that I&amp;rsquo;ve actually learned anything really about the SDK, about RISC-V&amp;hellip;&lt;/p&gt;
&lt;h2 id=&#34;pulling-it-apart&#34;&gt;Pulling it Apart&lt;/h2&gt;
&lt;p&gt;One thing I will say about the &lt;a href=&#34;https://docs.espressif.com/projects/vscode-esp-idf-extension/en/latest/&#34;&gt;VSCode plugin&lt;/a&gt; is that it did help making a new project off of a base template and that is nice. I will look to see if that&amp;rsquo;s a feature of the idf.&lt;/p&gt;
&lt;p&gt;Starting from the blink example I tore out a lot of code and deleted a lot of files.&lt;/p&gt;
&lt;p&gt;Tore out the specialized &lt;a href=&#34;https://docs.espressif.com/projects/idf-build-apps/en/latest/explanations/config_rules.html&#34;&gt;config stuff&lt;/a&gt;, left in the logging&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/carlynorama/esp32c6_tests/tree/simple_blink&#34;&gt;https://github.com/carlynorama/esp32c6_tests/tree/simple_blink&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-C&#34; data-lang=&#34;C&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// Needed for logging to serial monitor
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#include&lt;/span&gt; &lt;span style=&#34;color:#6e738d;font-weight:bold;font-style:italic&#34;&gt;&amp;lt;stdio.h&amp;gt;&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#include&lt;/span&gt; &lt;span style=&#34;color:#6e738d;font-weight:bold;font-style:italic&#34;&gt;&amp;#34;esp_log.h&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// Needed for portTICK_PERIOD_MS
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#include&lt;/span&gt; &lt;span style=&#34;color:#6e738d;font-weight:bold;font-style:italic&#34;&gt;&amp;#34;freertos/FreeRTOS.h&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#include&lt;/span&gt; &lt;span style=&#34;color:#6e738d;font-weight:bold;font-style:italic&#34;&gt;&amp;#34;freertos/task.h&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// Needed for io pins
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#include&lt;/span&gt; &lt;span style=&#34;color:#6e738d;font-weight:bold;font-style:italic&#34;&gt;&amp;#34;driver/gpio.h&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#define BLINK_GPIO 15
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#define BLINK_PERIOD 2000
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// logging prefix
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;const&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;char&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;*&lt;/span&gt;TAG &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;simple_blink&amp;#34;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;uint8_t&lt;/span&gt; s_led_state &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;0&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;void&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;blink_led&lt;/span&gt;(&lt;span style=&#34;color:#ed8796&#34;&gt;void&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;/* Set the GPIO level according to the state (LOW or HIGH)*/&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#8aadf4&#34;&gt;gpio_set_level&lt;/span&gt;(BLINK_GPIO, s_led_state);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;void&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;configure_led&lt;/span&gt;(&lt;span style=&#34;color:#ed8796&#34;&gt;void&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#8aadf4&#34;&gt;ESP_LOGI&lt;/span&gt;(TAG, &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Example configured to blink GPIO LED!&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#8aadf4&#34;&gt;gpio_reset_pin&lt;/span&gt;(BLINK_GPIO);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;/* Set the GPIO as a push/pull output */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#8aadf4&#34;&gt;gpio_set_direction&lt;/span&gt;(BLINK_GPIO, GPIO_MODE_OUTPUT);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;void&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;app_main&lt;/span&gt;(&lt;span style=&#34;color:#ed8796&#34;&gt;void&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;/* Configure the peripheral according to the LED type */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#8aadf4&#34;&gt;configure_led&lt;/span&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;while&lt;/span&gt; (&lt;span style=&#34;color:#f5a97f&#34;&gt;1&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// pin HIGH is __LED OFF__ for the XIAO built in LED. 
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;        &lt;span style=&#34;color:#8aadf4&#34;&gt;ESP_LOGI&lt;/span&gt;(TAG, &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Turning the LED %s!&amp;#34;&lt;/span&gt;, s_led_state &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;==&lt;/span&gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;true&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;?&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;OFF&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;ON&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#8aadf4&#34;&gt;blink_led&lt;/span&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;/* Toggle the LED state */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        s_led_state &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;!&lt;/span&gt;s_led_state;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// calculating the millis by hand based on the crystal speed is 
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// ANNNNNOOOOOOYYYYING. Keeping FreeRTOS. 
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;        &lt;span style=&#34;color:#8aadf4&#34;&gt;vTaskDelay&lt;/span&gt;(BLINK_PERIOD &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;/&lt;/span&gt; portTICK_PERIOD_MS);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Links to the functions that are left:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://docs.espressif.com/projects/esp-idf/en/v5.5.1/esp32c6/api-reference/peripherals/gpio.html#_CPPv414gpio_set_level10gpio_num_t8uint32_t&#34;&gt;gpio_set_level&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://docs.espressif.com/projects/esp-idf/en/v5.5.1/esp32c6/api-reference/peripherals/gpio.html#_CPPv414gpio_reset_pin10gpio_num_t&#34;&gt;gpio_reset_pin&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://docs.espressif.com/projects/esp-idf/en/v5.5.1/esp32c6/api-reference/peripherals/gpio.html#_CPPv418gpio_set_direction10gpio_num_t11gpio_mode_t&#34;&gt;gpio_set_direction&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://en.wikipedia.org/wiki/Push%E2%80%93pull_output&#34;&gt;more on push-pull outputs&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://docs.espressif.com/projects/esp-idf/en/v5.5.1/esp32c6/api-reference/system/log.html#c.ESP_LOGI&#34;&gt;ESP_LOGI&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;how it &lt;a href=&#34;https://esp32.com/viewtopic.php?t=5364&#34;&gt;differs from &lt;code&gt;printf&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://docs.espressif.com/projects/esp-idf/en/v5.5.1/esp32c6/api-reference/system/freertos_idf.html#_CPPv410vTaskDelayK10TickType_t&#34;&gt;vTaskDelay and portTICK_PERIOD_MS&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;also available: &lt;a href=&#34;https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/94cb87ad30a638dfc22585954494becea19918e6/include/projdefs.h#L42&#34;&gt;pdMS_TO_TICKS&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;blink-without-the-sdk&#34;&gt;Blink without the SDK?&lt;/h2&gt;
&lt;p&gt;To do this without the SDK, one has to do things like the make a vector table, etc. I found one example that did that for an older esp32 chip that was not a RISC-V.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/aykevl/esp32-minimal&#34;&gt;https://github.com/aykevl/esp32-minimal&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I think I want to save that energy for once I&amp;rsquo;ve started writing is Swift, if at all this project.&lt;/p&gt;
&lt;h2 id=&#34;summary&#34;&gt;Summary&lt;/h2&gt;
&lt;p&gt;Pretty smooth sailing. Next post, blinking with Swift.&lt;/p&gt;
</description>
    </item>
    
    
    
    <item>
      <title>Swift Embedded Sept 2025 Link Dump</title>
      <link>https://whynotestflight.com/excuses/swift-embedded-sept-2025-link-dump/</link>
      <pubDate>Wed, 03 Sep 2025 00:00:00 +0000</pubDate>
      
      <guid>https://whynotestflight.com/excuses/swift-embedded-sept-2025-link-dump/</guid>
      <description>&lt;p&gt;I have a bunch of notes in unpublished posts from 2024, which some day I&amp;rsquo;ll go back and publish. In the mean time I will just pull out a bunch of links from then and new ones that will help with the current project.&lt;/p&gt;
&lt;h2 id=&#34;official&#34;&gt;Official&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://docs.swift.org/embedded/documentation/embedded/&#34;&gt;https://docs.swift.org/embedded/documentation/embedded/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/swiftlang/swift-embedded-examples&#34;&gt;https://github.com/swiftlang/swift-embedded-examples&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/swiftlang/swift-evolution/blob/main/visions/embedded-swift.md&#34;&gt;https://github.com/swiftlang/swift-evolution/blob/main/visions/embedded-swift.md&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://docs.swift.org/embedded/documentation/embedded/languagesubset/&#34;&gt;https://docs.swift.org/embedded/documentation/embedded/languagesubset/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://forums.swift.org/c/development/embedded&#34;&gt;https://forums.swift.org/c/development/embedded&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;related: &lt;a href=&#34;https://forums.swift.org/c/related-projects/swift-for-webassembly/&#34;&gt;https://forums.swift.org/c/related-projects/swift-for-webassembly/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;official-manufacturer&#34;&gt;Official Manufacturer&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://developer.espressif.com/tags/swift/&#34;&gt;https://developer.espressif.com/tags/swift/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://developer.espressif.com/blog/build-embedded-swift-application-for-esp32c6/&#34;&gt;https://developer.espressif.com/blog/build-embedded-swift-application-for-esp32c6/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;specific-forum-posts&#34;&gt;Specific Forum Posts&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://forums.swift.org/t/embedded-swift-linkage-model/81441&#34;&gt;https://forums.swift.org/t/embedded-swift-linkage-model/81441&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;mine about supercon badge: &lt;a href=&#34;https://forums.swift.org/t/example-pico-w-code-works-on-supercon-badge/75769/8&#34;&gt;https://forums.swift.org/t/example-pico-w-code-works-on-supercon-badge/75769/8&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://forums.swift.org/t/alternative-malloc-implementations-tcmalloc-jemalloc-mimalloc/80473/4&#34;&gt;https://forums.swift.org/t/alternative-malloc-implementations-tcmalloc-jemalloc-mimalloc/80473/4&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;misc-repos-and-notes&#34;&gt;Misc Repos And Notes&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://georgik.rocks/wp-content/talks/2025-07-11-embedded-swift-community-hour/2025-07-11-embedded-swift-community-hour.pdf&#34;&gt;https://georgik.rocks/wp-content/talks/2025-07-11-embedded-swift-community-hour/2025-07-11-embedded-swift-community-hour.pdf&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/georgik/esp32-sdl3-swift-example&#34;&gt;https://github.com/georgik/esp32-sdl3-swift-example&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/georgik/esp32-c6-swift-baremetal&#34;&gt;https://github.com/georgik/esp32-c6-swift-baremetal&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/georgik/swift-xtensa/blob/main/swift-xtensa-build.sh&#34;&gt;https://github.com/georgik/swift-xtensa/blob/main/swift-xtensa-build.sh&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/georgik/esp32-sdl3-swift-example&#34;&gt;https://github.com/georgik/esp32-sdl3-swift-example&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/maartin0/arduino-swift-esp32-examples&#34;&gt;https://github.com/maartin0/arduino-swift-esp32-examples&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/swiftlang/swift-embedded-examples/pull/98&#34;&gt;https://github.com/swiftlang/swift-embedded-examples/pull/98&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/Sameesunkaria/swift-flipperzero-hello&#34;&gt;https://github.com/Sameesunkaria/swift-flipperzero-hello&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;(currently private) &lt;a href=&#34;https://github.com/carlynorama/_SwiftEmbeddedHello&#34;&gt;https://github.com/carlynorama/_SwiftEmbeddedHello&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/carlynorama/swift-pico-w-hello&#34;&gt;https://github.com/carlynorama/swift-pico-w-hello&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</description>
    </item>
    
    
    
    <item>
      <title>Podman: How do I write a container that will do a build?</title>
      <link>https://whynotestflight.com/excuses/podman-how-do-i-write-a-container-that-will-do-a-build/</link>
      <pubDate>Tue, 02 Sep 2025 00:00:00 +0000</pubDate>
      
      <guid>https://whynotestflight.com/excuses/podman-how-do-i-write-a-container-that-will-do-a-build/</guid>
      <description>&lt;p&gt;In &lt;a href=&#34;https://whynotestflight.com/excuses/podman-how-do-i-deploy-a-hummingbird-app-server/&#34;&gt;yesterday&amp;rsquo;s notes&lt;/a&gt; I used a locally compiled binary with a very slim docker file. This can work out fine, but what comes recommended by Vapor and Hummingbird? Can I understand those files yet?&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/vapor/template&#34;&gt;https://github.com/vapor/template&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/hummingbird-project/template&#34;&gt;https://github.com/hummingbird-project/template&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;What I&amp;rsquo;ve figure out by now is that those files have a build section that will spin up a container to do the compile, no cross compiling SDK needed. Potentially that means the app service will do that compile for me on the hardware that the binary will run on? So I don&amp;rsquo;t even have to know what the underlying architecture is? Interesting&amp;hellip; And then also how does that get worked in to the fee?&lt;/p&gt;
&lt;p&gt;NOTE: (One &lt;a href=&#34;https://github.com/Cyberbeni/MultiArchSwiftDockerfileExample/blob/650fe354e4b40e827e412bd48521833a643175ea/Dockerfile&#34;&gt;can use the static-sdk&lt;/a&gt; in a Containerfile compile, it&amp;rsquo;s just that one doesn&amp;rsquo;t have to.)&lt;/p&gt;
&lt;p&gt;But first steps first. Currently the project layout looks like:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;|- Container
|  |- binary
|  |  |- SmallestServer (binary)
|  |- Containerfile
|  
|- Sources
|  |- main.swift
|
|- buildLocalNRun.sh
|- Package.swift
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This is going to simplified to:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;|- Sources
|  |- main.swift
|
|- buildContainerNRun.sh
|- Containerfile
|- Package.swift
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The &lt;code&gt;Container&lt;/code&gt; folder can be deleted because there is no intermediate build product to store in the repo now.&lt;/p&gt;
&lt;h3 id=&#34;update-shell-script&#34;&gt;Update shell script&lt;/h3&gt;
&lt;p&gt;Update the script to remove any reference to building or compiling the package that way. The only thing that will build is the container.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-shell&#34; data-lang=&#34;shell&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#!/bin/sh
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## change in script if want to change.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;DEFAULT_PORT&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;8080&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;APP_NAME&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;SmallestServer&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;REPOSITORY&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;smallserver&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## can change at runtime &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## &amp;#39;zsh ./buildLocalNRun.sh debug&amp;#39; will run debug build instead.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;DEFAULT_CONFIG_VALUE&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;release&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;CONFIGURATION&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;${&lt;/span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;1&lt;/span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;:-&lt;/span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;$DEFAULT_CONFIG_VALUE&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;}&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## creates a tag based on the day and local time, e.g. mon104642&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;TAG&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;`&lt;/span&gt;date +&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;%a%H%M%S&amp;#34;&lt;/span&gt; | tr &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#39;[:upper:]&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#39;[:lower:]&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;`&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;podman build -t &lt;span style=&#34;color:#f4dbd6&#34;&gt;$REPOSITORY&lt;/span&gt;:&lt;span style=&#34;color:#f4dbd6&#34;&gt;$TAG&lt;/span&gt; .
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# no -d because want to see errors inline&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# this one will keep podman a little tidier. &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# podman run --rm --rmi -p $DEFAULT_PORT:8080 $REPOSITORY&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;podman run -p &lt;span style=&#34;color:#f4dbd6&#34;&gt;$DEFAULT_PORT&lt;/span&gt;:8080 &lt;span style=&#34;color:#f4dbd6&#34;&gt;$REPOSITORY&lt;/span&gt;:&lt;span style=&#34;color:#f4dbd6&#34;&gt;$TAG&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h4 id=&#34;a-different-containerfile&#34;&gt;A different Containerfile&lt;/h4&gt;
&lt;p&gt;So the two example Dockerfiles do a lot more than the tiny one. They &lt;a href=&#34;https://forums.swift.org/search?q=jemalloc&#34;&gt;change up the memory allocator&lt;/a&gt; (although how long it will be to &lt;a href=&#34;https://jasone.github.io/2025/06/12/jemalloc-postmortem/&#34;&gt;jemalloc&lt;/a&gt; tbd.), they make sure &lt;a href=&#34;https://forums.swift.org/search?q=backtracing&#34;&gt;backtracing works&lt;/a&gt;, move in resource files.&lt;/p&gt;
&lt;p&gt;What they are still doing is ending up with a mostly statically linked executable so the final container does not have to have Swift on it.  It appears to still need a C library? Something else the ubuntu base image has that alpine doesn&amp;rsquo;t?&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s go through the Vapor example section by section.&lt;/p&gt;
&lt;h5 id=&#34;the-build-section&#34;&gt;The Build Section&lt;/h5&gt;
&lt;p&gt;Difference #1, there is a &lt;em&gt;named&lt;/em&gt; build section based on an &lt;a href=&#34;https://github.com/swiftlang/swift-docker/blob/28756f801d3772456301075fcb70b1ef5cda0b6b/6.1/ubuntu/24.04/Dockerfile&#34;&gt;image that has Swift installed&lt;/a&gt;.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-Dockerfile&#34; data-lang=&#34;Dockerfile&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# ================================&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# Build image&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;### CHECK OUT THAT NAME after the AS!! &lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;FROM&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;swift:6.1-noble&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;AS&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;build&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Then the base image gets updated, &lt;a href=&#34;https://github.com/vapor/vapor/issues/2493&#34;&gt;jemalloc gets installed&lt;/a&gt;, &lt;a href=&#34;https://unix.stackexchange.com/questions/217369/clear-apt-get-list&#34;&gt;apt/lists gets cleaned out&lt;/a&gt;&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-shell&#34; data-lang=&#34;shell&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# Install OS updates&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;RUN &lt;span style=&#34;color:#91d7e3&#34;&gt;export&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;DEBIAN_FRONTEND&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt;noninteractive &lt;span style=&#34;color:#f4dbd6&#34;&gt;DEBCONF_NONINTERACTIVE_SEEN&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#91d7e3&#34;&gt;true&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;amp;&amp;amp;&lt;/span&gt; apt-get -q update &lt;span style=&#34;color:#8aadf4&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;amp;&amp;amp;&lt;/span&gt; apt-get -q dist-upgrade -y &lt;span style=&#34;color:#8aadf4&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;amp;&amp;amp;&lt;/span&gt; apt-get install -y libjemalloc-dev &lt;span style=&#34;color:#8aadf4&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;amp;&amp;amp;&lt;/span&gt; rm -rf /var/lib/apt/lists/*
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Create a build area and move the project files into it, with a good reason to do the dependencies first (caching the dependencies).&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-Dockerfile&#34; data-lang=&#34;Dockerfile&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# Set up a build area&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;WORKDIR&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;/build&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# First just resolve dependencies.&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# This creates a cached layer that can be reused&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# as long as your Package.swift/Package.resolved&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# files do not change.&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;COPY&lt;/span&gt; ./Package.* ./&lt;span style=&#34;color:#ed8796&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;RUN&lt;/span&gt; swift package resolve &lt;span style=&#34;color:#8aadf4&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;&lt;/span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;$(&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;[&lt;/span&gt; -f ./Package.resolved &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;]&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;echo&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;--force-resolved-versions&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;||&lt;/span&gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;true&lt;/span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# Copy entire repo into container&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;COPY&lt;/span&gt; . .&lt;span style=&#34;color:#ed8796&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Then, the build gets run and the products of that get put in a new directory called &amp;ldquo;staging&amp;rdquo;. Additionally any extra resources get moved, too. The Vapor and Hummingbird Dockerfiles do the almost exactly the same commands, but the Hummingbird template does each command as a separate &lt;code&gt;RUN&lt;/code&gt;. Each run gets cached separately, so I can see the pros and cons to both.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The &lt;code&gt;--mount=type=cache,target=/build/.build&lt;/code&gt; line allows for &lt;a href=&#34;https://forums.swift.org/t/incremental-builds-with-swift-package-manager-and-linux-docker/26538&#34;&gt;incremental builds&lt;/a&gt;, it&amp;rsquo;s a &lt;a href=&#34;https://docs.docker.com/build/cache/optimize/&#34;&gt;docker directive&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;It&amp;rsquo;s a release build.&lt;/li&gt;
&lt;li&gt;The {{name}} is a product of the GitHub template&amp;hellip; FIND THEM ALL!&lt;/li&gt;
&lt;li&gt;&lt;code&gt;--static-swift-stdlib&lt;/code&gt; flag to &lt;a href=&#34;https://forums.swift.org/t/pitch-package-manager-statically-link-swift-runtime-libraries-by-default-on-supported-platforms/53900&#34;&gt;statically link the Swift runtime libraries&lt;/a&gt; for this platform. It still requires the same platform dependencies. For fully static there used to be a &lt;code&gt;--static-executable&lt;/code&gt;, but that&amp;rsquo;s gone now?&lt;/li&gt;
&lt;li&gt;tell the linker to use a different malloc (see links above about memory issues)&lt;/li&gt;
&lt;li&gt;move the binary&lt;/li&gt;
&lt;li&gt;move the resources Swift Package Manager knows about.&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-Dockerfile&#34; data-lang=&#34;Dockerfile&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## Skipped in hummingbird version because moves come after&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## WORKDIR /staging&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;RUN&lt;/span&gt; mkdir /staging&lt;span style=&#34;color:#ed8796&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# Build the application, with optimizations, with static linking, and using jemalloc&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# N.B.: The static version of jemalloc is incompatible with the static Swift runtime.&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;RUN&lt;/span&gt; --mount&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;type&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt;cache,target&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt;/build/.build &lt;span style=&#34;color:#8aadf4&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;&lt;/span&gt;    swift build -c release &lt;span style=&#34;color:#8aadf4&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;&lt;/span&gt;        --product &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;{{&lt;/span&gt;name&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;}}&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;&lt;/span&gt;        --static-swift-stdlib &lt;span style=&#34;color:#8aadf4&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;&lt;/span&gt;        -Xlinker -ljemalloc &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# Copy main executable to staging area&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;&lt;/span&gt;    cp &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;$(&lt;/span&gt;swift build -c release --show-bin-path&lt;span style=&#34;color:#c6a0f6&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;/{{name}}&amp;#34;&lt;/span&gt; /staging &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# Copy resources bundled by SPM to staging area&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;&lt;/span&gt;    find -L &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;$(&lt;/span&gt;swift build -c release --show-bin-path&lt;span style=&#34;color:#c6a0f6&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt; -regex &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#39;.*\.resources$&amp;#39;&lt;/span&gt; -exec cp -Ra &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;{}&lt;/span&gt; /staging &lt;span style=&#34;color:#8aadf4&#34;&gt;\;&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Change the pwd to staging and copy over the &lt;code&gt;swift-backtrace-static&lt;/code&gt; binary to it, to enable the backtracing library to work. That will be enabled in the second part. This would not be necessary if the base image for the deployment had swift installed, but then it would be HUGE.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-Dockerfile&#34; data-lang=&#34;Dockerfile&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# Switch to the staging area&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;WORKDIR&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;/staging&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# Copy static swift backtracer binary to staging area&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;RUN&lt;/span&gt; cp &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;/usr/libexec/swift/linux/swift-backtrace-static&amp;#34;&lt;/span&gt; ./&lt;span style=&#34;color:#ed8796&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Move files from the default Vapor folders. In Hummingbird for example, the &amp;ldquo;Public&amp;rdquo; folder is &amp;ldquo;public&amp;rdquo;&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-Dockerfile&#34; data-lang=&#34;Dockerfile&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# Copy any resources from the public directory and views directory if the directories exist&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# Ensure that by default, neither the directory nor any of its contents are writable.&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;RUN&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;[&lt;/span&gt; -d /build/Public &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;]&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;{&lt;/span&gt; mv /build/Public ./Public &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;amp;&amp;amp;&lt;/span&gt; chmod -R a-w ./Public; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;}&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;||&lt;/span&gt; true&lt;span style=&#34;color:#ed8796&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;RUN&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;[&lt;/span&gt; -d /build/Resources &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;]&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;{&lt;/span&gt; mv /build/Resources ./Resources &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;amp;&amp;amp;&lt;/span&gt; chmod -R a-w ./Resources; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;}&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;||&lt;/span&gt; true&lt;span style=&#34;color:#ed8796&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h5 id=&#34;the-deploy-section&#34;&gt;The Deploy section&lt;/h5&gt;
&lt;p&gt;About halfway down the file is another &lt;code&gt;FROM&lt;/code&gt; call, so a second image is being made. It can refer to the first with &lt;code&gt;--from=&lt;/code&gt; labels.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-Dockerfile&#34; data-lang=&#34;Dockerfile&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# ================================&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# Run image&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# ================================&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;FROM&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;ubuntu:noble&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This is a common base, &amp;ldquo;Noble Numbat&amp;rdquo; is the most recent &lt;a href=&#34;https://releases.ubuntu.com/noble/&#34;&gt;canonical release&lt;/a&gt;. It&amp;rsquo;s much bigger than &lt;code&gt;scratch&lt;/code&gt; or &lt;code&gt;alpine&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Then again run updates and clear the cache&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-Dockerfile&#34; data-lang=&#34;Dockerfile&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# Make sure all system packages are up to date, and install only essential packages.&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;RUN&lt;/span&gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;export&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;DEBIAN_FRONTEND&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt;noninteractive &lt;span style=&#34;color:#f4dbd6&#34;&gt;DEBCONF_NONINTERACTIVE_SEEN&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#91d7e3&#34;&gt;true&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;amp;&amp;amp;&lt;/span&gt; apt-get -q update &lt;span style=&#34;color:#8aadf4&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;amp;&amp;amp;&lt;/span&gt; apt-get -q dist-upgrade -y &lt;span style=&#34;color:#8aadf4&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;amp;&amp;amp;&lt;/span&gt; apt-get -q install -y &lt;span style=&#34;color:#8aadf4&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;&lt;/span&gt;      libjemalloc2 &lt;span style=&#34;color:#8aadf4&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;&lt;/span&gt;      ca-certificates &lt;span style=&#34;color:#8aadf4&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;&lt;/span&gt;      tzdata &lt;span style=&#34;color:#8aadf4&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# If your app or its dependencies import FoundationNetworking, also install `libcurl4`.&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;&lt;/span&gt;      &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# libcurl4 \&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# If your app or its dependencies import FoundationXML, also install `libxml2`.&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;&lt;/span&gt;      &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# libxml2 \&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;amp;&amp;amp;&lt;/span&gt; rm -r /var/lib/apt/lists/*&lt;span style=&#34;color:#ed8796&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Add a user and move everything from staging into their home directory&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-Dockerfile&#34; data-lang=&#34;Dockerfile&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# Create a vapor user and group with /app as its home directory&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;RUN&lt;/span&gt; useradd --user-group --create-home --system --skel /dev/null --home-dir /app vapor&lt;span style=&#34;color:#ed8796&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# Switch to the new home directory&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;WORKDIR&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;/app&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# Copy built executable and any staged resources from builder&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;COPY&lt;/span&gt; --from&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt;build --chown&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt;vapor:vapor /staging /app&lt;span style=&#34;color:#ed8796&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Enable backtracing and put the tool&amp;rsquo;s location in the environment&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-Dockerfile&#34; data-lang=&#34;Dockerfile&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# Provide configuration needed by the built-in crash reporter and some sensible default behaviors.&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;ENV&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;SWIFT_BACKTRACE&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt;enable&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt;yes,sanitize&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt;yes,threads&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt;all,images&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt;all,interactive&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt;no,swift-backtrace&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt;./swift-backtrace-static&lt;span style=&#34;color:#ed8796&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Switch to the user and run the program&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-Dockerfile&#34; data-lang=&#34;Dockerfile&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# Ensure all further commands run as the vapor user&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;USER&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;vapor:vapor&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# Let Docker bind to port 8080&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;EXPOSE&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;8080&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# Start the Vapor service when the image is run, default to listening on 8080 in production environment&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;ENTRYPOINT&lt;/span&gt; [&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;./{{name}}&amp;#34;&lt;/span&gt;]&lt;span style=&#34;color:#ed8796&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;CMD&lt;/span&gt; [&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;serve&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;--env&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;production&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;--hostname&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;0.0.0.0&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;--port&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;8080&amp;#34;&lt;/span&gt;]&lt;span style=&#34;color:#ed8796&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h5 id=&#34;the-redux&#34;&gt;The Redux&lt;/h5&gt;
&lt;p&gt;SOOOOOO&amp;hellip;. How much of this can be stripped out?&lt;/p&gt;
&lt;h6 id=&#34;what-i-left-out&#34;&gt;What I left out&lt;/h6&gt;
&lt;p&gt;I wouldn&amp;rsquo;t leave these out in production of for a template, but for this specific example seemed fine:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;app is tiny so improved linux allocator seemed worth trying to leave out.&lt;/li&gt;
&lt;li&gt;I also didn&amp;rsquo;t update&amp;hellip; because isn&amp;rsquo;t that what using a :latest is for?&lt;/li&gt;
&lt;li&gt;Copying resource files, because this example doesn&amp;rsquo;t have any&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Leaving out the allocator and updating was partially because I was going to try to use &lt;code&gt;scratch&lt;/code&gt; or &lt;code&gt;alpine&lt;/code&gt; for the deployment container. Scratch doesn&amp;rsquo;t have a package manager and &lt;a href=&#34;https://stackoverflow.com/questions/53389749/getting-apt-get-on-an-alpine-container&#34;&gt;alpine uses &lt;code&gt;apk&lt;/code&gt;&lt;/a&gt;, so I would have had to translate the command. Turns out I had to use &lt;code&gt;FROM ubuntu:noble&lt;/code&gt; anyway to prevent a dynamic library loading error? (See below)&lt;/p&gt;
&lt;h6 id=&#34;whats-new&#34;&gt;What&amp;rsquo;s new&lt;/h6&gt;
&lt;p&gt;What&amp;rsquo;s new from the previous section&amp;rsquo;s container file:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The whole build section, obviously!&lt;/li&gt;
&lt;li&gt;&lt;code&gt;FROM ubuntu:noble&lt;/code&gt;. Originally I thought I&amp;rsquo;d be able to use &lt;code&gt;alpine&lt;/code&gt; or &lt;code&gt;scratch&lt;/code&gt; instead, but the deployment container complained a missing dynamic library. Switching to ubuntu:noble made it go away&amp;hellip; TODO&amp;hellip; WHAT dynamic library was missing?&lt;/li&gt;
&lt;li&gt;because there&amp;rsquo;s an OS in the container re-added adding a user.&lt;/li&gt;
&lt;li&gt;Backtrace support.
&lt;ul&gt;
&lt;li&gt;copying the backtrace tool&lt;/li&gt;
&lt;li&gt;setting the env&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I had to run it and re-run it a few times to shake out all the errors so I got a good look at all the caching features which help A LOT.&lt;/p&gt;
&lt;h4 id=&#34;a-containerfile-that-builds&#34;&gt;A Containerfile that Builds!&lt;/h4&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-Dockerfile&#34; data-lang=&#34;Dockerfile&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# ================================&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# Build image&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# ================================&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;FROM&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;swift:6.1-noble&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;AS&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;build&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# Install OS updates&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;RUN&lt;/span&gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;export&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;DEBIAN_FRONTEND&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt;noninteractive &lt;span style=&#34;color:#f4dbd6&#34;&gt;DEBCONF_NONINTERACTIVE_SEEN&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#91d7e3&#34;&gt;true&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;amp;&amp;amp;&lt;/span&gt; apt-get -q update &lt;span style=&#34;color:#8aadf4&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;amp;&amp;amp;&lt;/span&gt; apt-get -q dist-upgrade -y&lt;span style=&#34;color:#ed8796&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# Set up a build area&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;WORKDIR&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;/build&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# First just resolve dependencies.&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# This creates a cached layer that can be reused&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# as long as your Package.swift/Package.resolved&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# files do not change.&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;COPY&lt;/span&gt; ./Package.* ./&lt;span style=&#34;color:#ed8796&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;RUN&lt;/span&gt; swift package resolve &lt;span style=&#34;color:#8aadf4&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;&lt;/span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;$(&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;[&lt;/span&gt; -f ./Package.resolved &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;]&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;echo&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;--force-resolved-versions&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;||&lt;/span&gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;true&lt;/span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# Copy entire repo into container&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;COPY&lt;/span&gt; . .&lt;span style=&#34;color:#ed8796&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;RUN&lt;/span&gt; mkdir /staging&lt;span style=&#34;color:#ed8796&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# Build the application, with optimizations, with static linking, and using jemalloc&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# N.B.: The static version of jemalloc is incompatible with the static Swift runtime.&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;RUN&lt;/span&gt; --mount&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;type&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt;cache,target&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt;/build/.build &lt;span style=&#34;color:#8aadf4&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;&lt;/span&gt;    swift build -c release &lt;span style=&#34;color:#8aadf4&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;&lt;/span&gt;        --product SmallestServer &lt;span style=&#34;color:#8aadf4&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;&lt;/span&gt;        --static-swift-stdlib &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;&lt;/span&gt;    cp &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;$(&lt;/span&gt;swift build -c release --show-bin-path&lt;span style=&#34;color:#c6a0f6&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;/SmallestServer&amp;#34;&lt;/span&gt; /staging&lt;span style=&#34;color:#ed8796&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# Switch to the staging area&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;WORKDIR&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;/staging&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# Copy static swift backtracer binary to staging area&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;RUN&lt;/span&gt; cp &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;/usr/libexec/swift/linux/swift-backtrace-static&amp;#34;&lt;/span&gt; ./&lt;span style=&#34;color:#ed8796&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# ================================&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# Run image&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# ================================&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# Most swift examples use Ubuntu. &lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;FROM&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;ubuntu:noble&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;RUN&lt;/span&gt; useradd &lt;span style=&#34;color:#8aadf4&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;&lt;/span&gt;    --user-group &lt;span style=&#34;color:#8aadf4&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;&lt;/span&gt;    --create-home &lt;span style=&#34;color:#8aadf4&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;&lt;/span&gt;    --system &lt;span style=&#34;color:#8aadf4&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;&lt;/span&gt;    --skel /dev/null &lt;span style=&#34;color:#8aadf4&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;&lt;/span&gt;     --home-dir /app &lt;span style=&#34;color:#8aadf4&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;&lt;/span&gt;     hummingbird&lt;span style=&#34;color:#ed8796&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# Switch to the new home directory&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;WORKDIR&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;/app&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# give the binary to the hummingbird user&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# COPY --from=build --chown=hbUser:hbGroup /staging /app/&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;COPY&lt;/span&gt; --from&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt;build --chown&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt;hummingbird:hummingbird /staging /app&lt;span style=&#34;color:#ed8796&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# Provide configuration needed by the built-in crash reporter and some sensible default behaviors.&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;ENV&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;SWIFT_BACKTRACE&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt;enable&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt;yes,sanitize&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt;yes,threads&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt;all,images&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt;all,interactive&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt;no,swift-backtrace&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt;./swift-backtrace-static&lt;span style=&#34;color:#ed8796&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# Ensure all further commands run as the hummingbird user&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# USER hbUser:hbGroup&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;USER&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;hummingbird:hummingbird&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# Let Docker bind to port 8080&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;EXPOSE&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;8080&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# Start the Hummingbird service when the image is run, default to listening on 8080 in production environment&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;RUN&lt;/span&gt; ls&lt;span style=&#34;color:#ed8796&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;ENTRYPOINT&lt;/span&gt; [&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;./SmallestServer&amp;#34;&lt;/span&gt;]&lt;span style=&#34;color:#ed8796&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;CMD&lt;/span&gt; [&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;]&lt;span style=&#34;color:#ed8796&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;summary&#34;&gt;Summary&lt;/h2&gt;
&lt;p&gt;There&amp;rsquo;s still a lot to learn about working with container. I&amp;rsquo;ll be switching to Swift Embedded for a bit and it&amp;rsquo;s possible I&amp;rsquo;ll use them for that. But I&amp;rsquo;ll keep linking to the series when something new comes up!&lt;/p&gt;
</description>
    </item>
    
    
    
    <item>
      <title>Podman: How do I deploy a Hummingbird App Server?</title>
      <link>https://whynotestflight.com/excuses/podman-how-do-i-deploy-a-hummingbird-app-server/</link>
      <pubDate>Mon, 01 Sep 2025 00:00:00 +0000</pubDate>
      
      <guid>https://whynotestflight.com/excuses/podman-how-do-i-deploy-a-hummingbird-app-server/</guid>
      <description>&lt;h2 id=&#34;what-is-hummingbird&#34;&gt;What is Hummingbird?&lt;/h2&gt;
&lt;p&gt;&lt;a href=&#34;https://hummingbird.codes&#34;&gt;Hummingbird&lt;/a&gt; is a very modular Swift based server framework build on top of &lt;a href=&#34;https://swiftonserver.com/using-swiftnio-fundamentals/&#34;&gt;SwiftNIO&lt;/a&gt;. It&amp;rsquo;s easy to use and it has a great community around it. (&lt;a href=&#34;https://github.com/hummingbird-project/hummingbird/discussions/150&#34;&gt;Why Hummingbird&lt;/a&gt;)&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://vapor.codes&#34;&gt;Vapor&lt;/a&gt; would also have been a great choice, but it comes fully bundled with more than I needed.&lt;/p&gt;
&lt;h2 id=&#34;whats-it-take-to-build-a-starter-server-for-a-container&#34;&gt;What&amp;rsquo;s it take to build a starter server for a container?&lt;/h2&gt;
&lt;p&gt;Not much! This is what it took for me to make the &lt;a href=&#34;https://github.com/carlynorama/HummingbirdExamples/tree/main/00_smallest_server&#34;&gt;00_smallest_server example&lt;/a&gt;&lt;/p&gt;
&lt;h3 id=&#34;create-a-start&#34;&gt;Create A Start&lt;/h3&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-shell&#34; data-lang=&#34;shell&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;mkdir -p 00_smallest_server
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;swift package init --type executable --name SmallestServer
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;swift package add-dependency https://github.com/hummingbird-project/hummingbird --from 2.16.0
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;update-mainswift&#34;&gt;Update main.swift&lt;/h3&gt;
&lt;p&gt;In main.swift add&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;Hummingbird&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;hostname&lt;/span&gt;: &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt; = &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;0.0.0.0&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;port&lt;/span&gt;: &lt;span style=&#34;color:#91d7e3&#34;&gt;Int&lt;/span&gt; = &lt;span style=&#34;color:#f5a97f&#34;&gt;8080&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;configuration&lt;/span&gt;: ApplicationConfiguration = .&lt;span style=&#34;color:#ed8796&#34;&gt;init&lt;/span&gt;(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    address: .hostname(hostname, port: port),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    serverName: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;SmallestServer&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;router&lt;/span&gt; = Router()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    .&lt;span style=&#34;color:#c6a0f6&#34;&gt;get&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;hello&amp;#34;&lt;/span&gt;) { request, &lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; -&amp;gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Hello&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// create application using router&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;app&lt;/span&gt; = Application(router: router, configuration:configuration)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// run hummingbird application&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; await app.runService()
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The code slightly modifies from &lt;a href=&#34;https://docs.hummingbird.codes/2.0/documentation/index/&#34;&gt;code from the docs page&lt;/a&gt; to make it work in a container. If not working in a container leaving the default in place &lt;a href=&#34;https://stackoverflow.com/questions/20778771/what-is-the-difference-between-0-0-0-0-127-0-0-1-and-localhost&#34;&gt;127.0.0.1, the local loop back&lt;/a&gt; is the better choice.&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;let app = Application(router: router)
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Old internet heads will balk at passing 0.0.0.0 because it means &amp;ldquo;listen on everything!&amp;rdquo; which could be a security risk. In a container that is apparently considered okay because it&amp;rsquo;s isolated, and these days will unlikely to have been given access to root. The container will be given an address once running which can be discovered with &lt;a href=&#34;https://podman.io/docs#inspecting-a-running-container&#34;&gt;inspect&lt;/a&gt;&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;podman inspect $CONTAINER_ID_OR_NAME | grep IPAddress
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;On linux one can instead bind to the specific IP a container is given by listening on &lt;a href=&#34;https://stackoverflow.com/a/43541732&#34;&gt;host.docker.internal&lt;/a&gt; (&lt;a href=&#34;https://docs.docker.com/desktop/features/networking/#i-cannot-ping-my-containers&#34;&gt;docs&lt;/a&gt;) or the more generic &lt;a href=&#34;https://stackoverflow.com/a/75913128&#34;&gt;podman equivalent&lt;/a&gt;&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;hostname&lt;/span&gt;: &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt; = &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;host.docker.internal&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;hostname&lt;/span&gt;: &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt; = &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;host.containers.internal&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;I have not seen this working myself. Something about Containers and that Mac&amp;rsquo;s run them in VMs and that Linux has cgroups? On Linux there may be other options like adding &lt;a href=&#34;https://stackoverflow.com/questions/50976362/bind-docker-container-loopback-to-the-host-loopback&#34;&gt;&lt;code&gt;--network=host&lt;/code&gt;&lt;/a&gt; to the run command. (Interesting convo on the Hummingbird discord! &lt;a href=&#34;https://hummingbird.codes&#34;&gt;link at bottom of page&lt;/a&gt;) (Built fine, core-dumped when running &amp;lsquo;Address not available (errno: 99)&amp;rsquo;)&lt;/p&gt;
&lt;h3 id=&#34;update-packageswift&#34;&gt;Update Package.swift&lt;/h3&gt;
&lt;p&gt;Update &lt;code&gt;Package.swift&lt;/code&gt; to add the dependency to the executable and require at least MacOS 14.0:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;PackageDescription&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;package&lt;/span&gt; = Package(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    name: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;SmallestServer&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    platforms : [.macOS(.v14)],
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    dependencies: [
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        .package(url: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;https://github.com/hummingbird-project/hummingbird&amp;#34;&lt;/span&gt;, from: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;2.16.0&amp;#34;&lt;/span&gt;),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    ],
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    targets: [
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// Targets are the basic building blocks of a package, defining a module or a test suite.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// Targets can depend on other targets in this package and products from dependencies.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        .executableTarget(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            name: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;SmallestServer&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            dependencies: [.product(name: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Hummingbird&amp;#34;&lt;/span&gt;, package: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;hummingbird&amp;#34;&lt;/span&gt;)]),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    ]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;build-and-run-in-the-background&#34;&gt;Build and run in the background&lt;/h3&gt;
&lt;p&gt;Slightly fancy version of building the package, running the server and going to the route in the browser.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-shell&#34; data-lang=&#34;shell&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;swift build
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;./.build/arm64-apple-macosx/debug/SmallestServer &amp;amp; &lt;span style=&#34;color:#91d7e3&#34;&gt;disown&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;open -a Safari http://127.0.0.1:8080/hello
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## also&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;curl &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;http://127.0.0.1:8080/hello&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Usually one chooses to build and run a swift package with &lt;code&gt;swift run&lt;/code&gt; and that works with Hummingbird apps too!&lt;/p&gt;
&lt;p&gt;However, I wanted to show launching the binary in background and disowning it to highlight a problem with hand deploying apps on a server. They need to be run in the background (the &lt;code&gt;&amp;amp;&lt;/code&gt;) and not quit when the terminal gets shut (the &lt;code&gt;disown&lt;/code&gt;). One might also see solutions with &lt;a href=&#34;https://www.gnu.org/savannah-checkouts/gnu/coreutils/manual/html_node/nohup-invocation.html&#34;&gt;nohup&lt;/a&gt;, &lt;a href=&#34;https://www.redhat.com/en/blog/introduction-tmux-linux&#34;&gt;tmux&lt;/a&gt;, &lt;a href=&#34;https://www.gnu.org/software/screen/manual/screen.html&#34;&gt;screen&lt;/a&gt;&amp;hellip;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://www.baeldung.com/linux/detach-process-from-terminal&#34;&gt;https://www.baeldung.com/linux/detach-process-from-terminal&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://superuser.com/questions/178587/how-do-i-detach-a-process-from-terminal-entirely&#34;&gt;https://superuser.com/questions/178587/how-do-i-detach-a-process-from-terminal-entirely&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://www.networkworld.com/article/969269/how-to-keep-processes-running-after-logging-off-in-linux.html&#34;&gt;https://www.networkworld.com/article/969269/how-to-keep-processes-running-after-logging-off-in-linux.html&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If one runs &lt;code&gt;ps&lt;/code&gt;, though, one will see that the process isn&amp;rsquo;t listed there anymore. To get the pid to kill it one will need to&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-shell&#34; data-lang=&#34;shell&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ps aux | grep SmallestServer
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#91d7e3&#34;&gt;kill&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;$PID&lt;/span&gt; &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# returned by ps aux&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## or&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;pKill SmallestServer
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Derived from a &lt;a href=&#34;https://unix.stackexchange.com/a/106848&#34;&gt;good stack exchange answer&lt;/a&gt; (but also available from reading &lt;code&gt;man ps&lt;/code&gt;) the &lt;code&gt;aux&lt;/code&gt; after the &lt;code&gt;ps&lt;/code&gt; corresponds to:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;a = show processes for all users
u = display the process&amp;#39;s user/owner with a name not a #
x = also show processes not attached to a terminal
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;So we&amp;rsquo;re looking trough all the processes being run by anyone and killing the one that has SmallestServer in the name.&lt;/p&gt;
&lt;p&gt;The thing is, a good sys admin will have &lt;a href=&#34;https://en.wikipedia.org/wiki/Systemd&#34;&gt;systemd&lt;/a&gt; kill user processes on logout, even if the process had been &lt;code&gt;disown&lt;/code&gt;&amp;rsquo;d. And even if they agree not to kill it this sys admin will have to agree &lt;a href=&#34;https://dev.to/elwin013/how-to-expose-local-service-using-nginx-and-ssh-1jmj&#34;&gt;to configure&lt;/a&gt; &lt;a href=&#34;https://dev.to/iaadidev/how-to-deploy-an-application-using-nginx-as-a-web-server-36a&#34;&gt;the server&lt;/a&gt; to expose your experimental &lt;a href=&#34;https://docs.nginx.com/nginx/admin-guide/web-server/web-server/&#34;&gt;process to the internet&lt;/a&gt;.  I mean, if it&amp;rsquo;s my server, I&amp;rsquo;m saying no.&lt;/p&gt;
&lt;p&gt;And if it&amp;rsquo;s just your server, and you just have this one little app&amp;hellip; who wants to knock about alone in a big echo-y machine all alone like that?&lt;/p&gt;
&lt;h2 id=&#34;get-the-server-into-a-container&#34;&gt;Get the Server into a Container&lt;/h2&gt;
&lt;p&gt;An easier way to get a simple app up on the internet is through a provider that offers some kind of &lt;a href=&#34;https://en.wikipedia.org/wiki/Platform_as_a_service&#34;&gt;Platform as a Service&lt;/a&gt; offering, which is a step up from the &lt;a href=&#34;https://en.wikipedia.org/wiki/Infrastructure_as_a_service&#34;&gt;Infrastructure as a Service&lt;/a&gt; model that a VPS might be a component of.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://www.freecodecamp.org/news/vps-vs-paas-how-to-choose-a-hosting-solution/&#34;&gt;https://www.freecodecamp.org/news/vps-vs-paas-how-to-choose-a-hosting-solution/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This business model probably only became viable because &lt;code&gt;Containers&lt;/code&gt; exist!&lt;/p&gt;
&lt;p&gt;There are several ways to get the app into a container that can be hosted on an app service, but this article will focus on what we&amp;rsquo;ve done before, cross compiling a statically linked binary that will be as small as possible.&lt;/p&gt;
&lt;h3 id=&#34;cross-compile-locally&#34;&gt;Cross Compile Locally&lt;/h3&gt;
&lt;p&gt;For this, first &lt;a href=&#34;https://whynotestflight.com/excuses/how-do-i-cross-compile-a-swift-statically-linked-binary/&#34;&gt;cross compile just a hello world&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;This section is essentially an evolution from the more general &lt;a href=&#34;https://whynotestflight.com/excuses/podman-how-do-i-make-a-new-image-from-a-base/#wrapping-a-binary&#34;&gt;Wrapping a Binary&lt;/a&gt; section from a couple days ago, but the &lt;code&gt;Containerfile&lt;/code&gt; will be a little bit different.&lt;/p&gt;
&lt;h4 id=&#34;shell-script&#34;&gt;Shell Script&lt;/h4&gt;
&lt;p&gt;So let&amp;rsquo;s take the steps from that last post and make them a &lt;code&gt;buildLocalNRun.sh&lt;/code&gt; script. The script below generates a tag based on the day and time and will do a release build by default.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-shell&#34; data-lang=&#34;shell&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#!/bin/sh
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## change in script if want to change.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;DEFAULT_PORT&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;8080&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## can change at runtime &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## &amp;#39;zsh ./buildLocalNRun.sh debug&amp;#39; will run debug build instead.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;DEFAULT_CONFIG_VALUE&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;release&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;CONFIGURATION&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;${&lt;/span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;1&lt;/span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;:-&lt;/span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;$DEFAULT_CONFIG_VALUE&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;}&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## make it if it doesn&amp;#39;t exist. The enclosing folder will exist because&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## The Containerfile is already there. &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;mkdir -p Container/binary/
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## Do the statically linked build&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;swift build -c &lt;span style=&#34;color:#f4dbd6&#34;&gt;$CONFIGURATION&lt;/span&gt; --swift-sdk x86_64-swift-linux-musl
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## Move it to the binary folder where the Containerfile thinks it is&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;cp .build/x86_64-swift-linux-musl/&lt;span style=&#34;color:#f4dbd6&#34;&gt;$CONFIGURATION&lt;/span&gt;/SmallestServer Container/binary/SmallestServer
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## creates a tag based on the day and local time, e.g. mon104642&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;TAG&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;`&lt;/span&gt;date +&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;%a%H%M%S&amp;#34;&lt;/span&gt; | tr &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#39;[:upper:]&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#39;[:lower:]&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;`&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;podman build -f Container/Containerfile -t smallserver:&lt;span style=&#34;color:#f4dbd6&#34;&gt;$TAG&lt;/span&gt; Container/
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# no -d because want to see errors inline&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# this one will keep podman a little tidier. &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# podman run --rm --rmi -p $DEFAULT_PORT:8080 smallserver&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;podman run -p &lt;span style=&#34;color:#f4dbd6&#34;&gt;$DEFAULT_PORT&lt;/span&gt;:8080 smallserver:&lt;span style=&#34;color:#f4dbd6&#34;&gt;$TAG&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h4 id=&#34;containerfile&#34;&gt;Containerfile&lt;/h4&gt;
&lt;p&gt;And for this example an even more stripped down Containerfile:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-Dockerfile&#34; data-lang=&#34;Dockerfile&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;FROM&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;scratch&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# Make and change into app directory&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;WORKDIR&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;/app&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# The binary directory contains the compiled app &lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;COPY&lt;/span&gt; ./binary/ /app/&lt;span style=&#34;color:#ed8796&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# Let Docker bind to port 8080&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;EXPOSE&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;8080&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# Start the Hummingbird service when the image is run, default to listening on 8080 in production environment&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;ENTRYPOINT&lt;/span&gt; [&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;./SmallestServer&amp;#34;&lt;/span&gt;]&lt;span style=&#34;color:#ed8796&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Notice the different &lt;a href=&#34;https://docs.docker.com/build/building/base-images/&#34;&gt;base image&lt;/a&gt;. This time it&amp;rsquo;s &lt;a href=&#34;https://hub.docker.com/_/scratch/&#34;&gt;scratch&lt;/a&gt; instead of &lt;a href=&#34;https://hub.docker.com/_/alpine&#34;&gt;alpine&lt;/a&gt;. The &lt;code&gt;scratch&lt;/code&gt; container provides NOTHING to the app&amp;rsquo;s context while the &lt;code&gt;alpine&lt;/code&gt; container still provides some basic operating system tools. Our project needs nothing from an OS, so it&amp;rsquo;s safer not to give it anything that can be exploited. That said, scratch containers can&amp;rsquo;t be ssh&amp;rsquo;d into to troubleshoot and other ENV problems can crop up. It isn&amp;rsquo;t the easiest base image to work with if size isn&amp;rsquo;t an issue. It&amp;rsquo;s not that I didn&amp;rsquo;t make a new user in the Containerfile because I was lazy. I didn&amp;rsquo;t make a new user in the Containerfile because I couldn&amp;rsquo;t.&lt;/p&gt;
&lt;h4 id=&#34;linker-directive-in-packageswift-optional&#34;&gt;Linker directive in Package.swift (Optional)&lt;/h4&gt;
&lt;p&gt;Like in the &lt;a href=&#34;https://whynotestflight.com/excuses/how-do-i-cross-compile-a-swift-statically-linked-binary/#applying-to-an-existing-project&#34;&gt;static sdk example&lt;/a&gt;, to make our resulting release build image even smaller optionally add a &lt;a href=&#34;https://blog.thea.codes/the-most-thoroughly-commented-linker-script/&#34;&gt;linker&lt;/a&gt; directive to &lt;a href=&#34;https://llvm.org/docs/CommandGuide/llvm-strip.html&#34;&gt;strip symbols from the object file&lt;/a&gt; to &lt;code&gt;Package.swift&lt;/code&gt;.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    targets: [
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        .executableTarget(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            name: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;hello-world&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            dependencies: [
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                .product(name: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Hummingbird&amp;#34;&lt;/span&gt;, package: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;hummingbird&amp;#34;&lt;/span&gt;),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                .product(name: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;ArgumentParser&amp;#34;&lt;/span&gt;, package: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;swift-argument-parser&amp;#34;&lt;/span&gt;),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            ],
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            linkerSettings: [
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// STRIP_STYLE = all&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;				.unsafeFlags([&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;-Xlinker&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;-s&amp;#34;&lt;/span&gt;], .when(configuration: .release)), 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;			]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        )
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    ]
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;push-to-registry&#34;&gt;Push to Registry&lt;/h2&gt;
&lt;p&gt;The current build scripts will launch the Hummingbird app on the local computer. To hand it off to an App Server, it goes to a registry first.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://whynotestflight.com/excuses/podman-how-do-i-preserve-or-share-my-image/#option-4-using-push-to-a-remote-registry&#34;&gt;Previously&lt;/a&gt; I pushed an image to Digital Ocean and Docker Hub.&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s add the push to Docker Hub to the bottom of the script:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-zsh&#34; data-lang=&#34;zsh&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## COMMENT OUT THE RUN!!&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# podman run -p $DEFAULT_PORT:8080 $REPOSITORY:$TAG&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## DON&amp;#39;T FORGET TO LOGIN to docker either using&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## `docker login` or `podman login`&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;DOCKER_USER&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;someusername&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;REMOTE_REPOSITORY&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;smalltest&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;REMOTE_TAG&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;v1&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;podman tag localhost/smallserver:&lt;span style=&#34;color:#f4dbd6&#34;&gt;$TAG&lt;/span&gt; docker.io/&lt;span style=&#34;color:#f4dbd6&#34;&gt;$DOCKER_USER&lt;/span&gt;/&lt;span style=&#34;color:#f4dbd6&#34;&gt;$REMOTE_REPOSITORY&lt;/span&gt;:&lt;span style=&#34;color:#f4dbd6&#34;&gt;$REMOTE_TAG&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;podman push docker.io/&lt;span style=&#34;color:#f4dbd6&#34;&gt;$DOCKER_USER&lt;/span&gt;/&lt;span style=&#34;color:#f4dbd6&#34;&gt;$REMOTE_REPOSITORY&lt;/span&gt;:&lt;span style=&#34;color:#f4dbd6&#34;&gt;$REMOTE_TAG&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;See the result here: &lt;a href=&#34;https://hub.docker.com/repository/docker/carlynorama/smalltest/general&#34;&gt;https://hub.docker.com/repository/docker/carlynorama/smalltest/general&lt;/a&gt;&lt;/p&gt;
&lt;h3 id=&#34;make-it-alive&#34;&gt;Make it ALIVE!&lt;/h3&gt;
&lt;p&gt;The next step is to sign up for a Digital Ocean App Server and link it to a repository in a registry.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;DigitalOceanAppServer.png&#34; alt=&#34;Screen capture of the Digital Ocean App Server creation interface showing the options once &amp;ldquo;from a registry is selected&amp;rdquo;&#34;&gt;&lt;/p&gt;
&lt;p&gt;Honestly, this was the least time consuming part of this whole process.&lt;/p&gt;
&lt;p&gt;Changed nothing about the defaults except to move my service tier down from the 12/mo to the 5/mo service.  And it worked!&lt;/p&gt;
&lt;p&gt;Although have a &lt;a href=&#34;https://github.com/carlynorama/HelloServer/tree/deployTests&#34;&gt;different hummingbird server&lt;/a&gt; running there at the moment&amp;hellip;&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;LiveSite.png&#34; alt=&#34;Screen capture the live site, although a slightly different site than the one in this demo.&amp;quot;&#34;&gt;&lt;/p&gt;
&lt;h2 id=&#34;next-up&#34;&gt;Next Up&amp;hellip;&lt;/h2&gt;
&lt;p&gt;Next is switching from the most minimal set up to one based on the Vapor and Hummingbird templates, which are more robust.&lt;/p&gt;
</description>
    </item>
    
    
    
    <item>
      <title>How do I cross compile a Swift statically linked binary?</title>
      <link>https://whynotestflight.com/excuses/how-do-i-cross-compile-a-swift-statically-linked-binary/</link>
      <pubDate>Sun, 31 Aug 2025 00:00:00 +0000</pubDate>
      
      <guid>https://whynotestflight.com/excuses/how-do-i-cross-compile-a-swift-statically-linked-binary/</guid>
      <description>&lt;h2 id=&#34;resources&#34;&gt;Resources&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://www.swift.org/documentation/articles/static-linux-getting-started.html&#34;&gt;https://www.swift.org/documentation/articles/static-linux-getting-started.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Swift to the cloud in a single step - Euan Harris: &lt;a href=&#34;https://www.youtube.com/watch?v=9AaINsCfZzw&#34;&gt;https://www.youtube.com/watch?v=9AaINsCfZzw&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;WWDC24: What’s new in Swift | Apple - (7:23) &lt;a href=&#34;https://www.youtube.com/watch?v=17fZZ1v_N2U&amp;amp;t=457s&#34;&gt;https://www.youtube.com/watch?v=17fZZ1v_N2U&amp;amp;t=457s&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://theswiftdev.com/building-static-and-dynamic-swift-libraries-using-the-swift-compiler/&#34;&gt;https://theswiftdev.com/building-static-and-dynamic-swift-libraries-using-the-swift-compiler/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/swiftlang/swift-evolution/blob/main/proposals/0387-cross-compilation-destinations.md&#34;&gt;https://github.com/swiftlang/swift-evolution/blob/main/proposals/0387-cross-compilation-destinations.md&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/swiftlang/swift-sdk-generator&#34;&gt;https://github.com/swiftlang/swift-sdk-generator&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In the post about &lt;a href=&#34;https://whynotestflight.com/excuses/podman-how-do-i-make-a-new-image-from-a-base/&#34;&gt;podman and sharing images&lt;/a&gt; I referenced having a linux static binary available to use in my container image.&lt;/p&gt;
&lt;p&gt;How&amp;rsquo;d I get it?&lt;/p&gt;
&lt;p&gt;The first thing I did was simply follow the &lt;a href=&#34;https://www.swift.org/documentation/articles/static-linux-getting-started.html&#34;&gt;tutorial with a demo hello app&lt;/a&gt; provided by Swift.org.&lt;/p&gt;
&lt;p&gt;To complete it I needed two things, an NON-Xcode open source version of Swift and a Swift Linux SDK.&lt;/p&gt;
&lt;h2 id=&#34;non-xcode-swift&#34;&gt;Non-Xcode Swift&lt;/h2&gt;
&lt;p&gt;In the shell where one intends to compile it&amp;rsquo;s important to run&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-shell&#34; data-lang=&#34;shell&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;which swift
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;swift --version
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;to make sure the non-Xcode version of Swift will be used. I had trouble with VSCode&amp;rsquo;s integrated terminal defaulting to the XCode toolchain.  I haven&amp;rsquo;t bothered to &lt;a href=&#34;https://www.swift.org/documentation/articles/getting-started-with-vscode-swift.html#advanced-toolchain-selection&#34;&gt;troubleshoot too deeply&lt;/a&gt;, but it seems to be tied to the &lt;code&gt;xcode-select&lt;/code&gt; version being preferred by default. This may have &lt;a href=&#34;https://forums.swift.org/t/gsoc-2025-bringing-swiftly-support-to-vs-code/81886&#34;&gt;JUST been addressed&lt;/a&gt;, but for now I just used Terminal instead.&lt;/p&gt;
&lt;h3 id=&#34;swiftly&#34;&gt;Swiftly&lt;/h3&gt;
&lt;p&gt;If you haven&amp;rsquo;t installed Swiftly on your Mac, it&amp;rsquo;s a good choice for switching between different version of Swift. It&amp;rsquo;s now the recommended path on the &lt;a href=&#34;https://www.swift.org/install/macos/&#34;&gt;swift/install/macos&lt;/a&gt; page&lt;/p&gt;
&lt;p&gt;I used&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-shell&#34; data-lang=&#34;shell&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# https://formulae.brew.sh/formula/swiftly&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;brew install swiftly
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;but it&amp;rsquo;s doable by hand:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-shell&#34; data-lang=&#34;shell&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;curl -O https://download.swift.org/swiftly/darwin/swiftly.pkg &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;&lt;/span&gt;installer -pkg swiftly.pkg -target CurrentUserHomeDirectory &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;&lt;/span&gt;~/.swiftly/bin/swiftly init --quiet-shell-followup &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;&lt;/span&gt;. &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;${&lt;/span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;SWIFTLY_HOME_DIR&lt;/span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;:-&lt;/span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;$HOME&lt;/span&gt;/.swiftly&lt;span style=&#34;color:#a6da95&#34;&gt;}&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;/env.sh&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#91d7e3&#34;&gt;hash&lt;/span&gt; -r
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Example usage:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-shell&#34; data-lang=&#34;shell&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## install and switch&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;swiftly install --use latest
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;which swift
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# /Users/$USER/.swiftly/bin/swift&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;swift --version
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# Apple Swift version 6.1.2 (swift-6.1.2-RELEASE)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# Target: arm64-apple-macosx15.0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## to see other toolchains visible to Swiftly&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;swiftly list 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## to switch&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;swiftly use &lt;span style=&#34;color:#f4dbd6&#34;&gt;$SOME_TOOLCHAIN_IN_LIST&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;linux-sdk&#34;&gt;Linux SDK&lt;/h2&gt;
&lt;p&gt;Since I&amp;rsquo;m compiling on a Mac I need the software dev kit that will work for my target version of Linux.&lt;/p&gt;
&lt;p&gt;I found the reference I needed halfway down &lt;a href=&#34;https://www.swift.org/install/macos/&#34;&gt;the main install page&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The dev kit needs to match the version of Swift one is compiling with, so since I am using the latest release (6.1.2), that&amp;rsquo;s the dev kit I need.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-shell&#34; data-lang=&#34;shell&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;swift sdk install https://download.swift.org/swift-6.1.2-release/static-sdk/swift-6.1.2-RELEASE/swift-6.1.2-RELEASE_static-linux-0.0.1.artifactbundle.tar.gz
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; --checksum df0b40b9b582598e7e3d70c82ab503fd6fbfdff71fd17e7f1ab37115a0665b3b
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;To check that its there&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-shell&#34; data-lang=&#34;shell&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;swift sdk list
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The installer put the sdk at:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Real and the same:
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;/System/Volumes/Data/Users/$USER/Library/org.swift.swiftpm/swift-sdks/&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;/Users/$USER/Library/org.swift.swiftpm/swift-sdks/&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Symlink:
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;/Users/$USER/.swiftpm/swift-sdks&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;building-an-example-package&#34;&gt;Building An Example Package&lt;/h2&gt;
&lt;p&gt;These are all the steps to run and test the the example, assuming one has a remote machine to port it to. If not check out some of the &lt;a href=&#34;https://whynotestflight.com/excuses/podman-how-do-i-get-and-edit-an-image-on-macos/&#34;&gt;podman series&lt;/a&gt; to run it in a container!&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-shell&#34; data-lang=&#34;shell&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#91d7e3&#34;&gt;cd&lt;/span&gt; Place/For/Code
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;mkdir hello
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#91d7e3&#34;&gt;cd&lt;/span&gt; hello
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;swift package init --type executable
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;swift build --swift-sdk x86_64-swift-linux-musl
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;file .build/x86_64-swift-linux-musl/debug/hello
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;scp .build/x86_64-swift-linux-musl/debug/hello username@remote.example.com:~/hello
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ssh username@remote.example.com ~/hello
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;applying-to-an-existing-project&#34;&gt;Applying To an Existing Project&lt;/h2&gt;
&lt;p&gt;With the SDK&amp;rsquo;s installed one can do this for any Swift package with an executable†.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-shell&#34; data-lang=&#34;shell&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#91d7e3&#34;&gt;cd&lt;/span&gt; /location/of/MyPackage
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;swift build -configuration release --swift-sdk x86_64-swift-linux-musl
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;file .build/x86_64-swift-linux-musl/release/&lt;span style=&#34;color:#f4dbd6&#34;&gt;$EXECUTABLE_NAME&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Once moving into release mode do consider having the linker perform a full &lt;a href=&#34;https://llvm.org/docs/CommandGuide/llvm-strip.html&#34;&gt;strip&lt;/a&gt;. It makes the binaries much smaller, and one could argue its a good idea to do for binaries going on internet exposed machines in general. I had forgotten about this &lt;a href=&#34;https://forums.swift.org/t/de-minimis-server-containerfile-for-a-musl-based-static-linking/81887/12&#34;&gt;until reminded!&lt;/a&gt;&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    targets: [
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        .executableTarget(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            name: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;hello-world&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            dependencies: [
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                .product(name: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Hummingbird&amp;#34;&lt;/span&gt;, package: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;hummingbird&amp;#34;&lt;/span&gt;),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                .product(name: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;ArgumentParser&amp;#34;&lt;/span&gt;, package: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;swift-argument-parser&amp;#34;&lt;/span&gt;),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            ],
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            linkerSettings: [
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;				.unsafeFlags([&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;-Xlinker&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;-s&amp;#34;&lt;/span&gt;], .when(configuration: .release)), &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// STRIP_STYLE = all&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;			]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        )
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    ]
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ul&gt;
&lt;li&gt;About strip in general:
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://unix.stackexchange.com/questions/2969/what-are-stripped-and-not-stripped-executables-in-unix&#34;&gt;https://unix.stackexchange.com/questions/2969/what-are-stripped-and-not-stripped-executables-in-unix&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://linuxtldr.com/strip-command/&#34;&gt;https://linuxtldr.com/strip-command/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Its companion strings : &lt;a href=&#34;https://www.howtogeek.com/427805/how-to-use-the-strings-command-on-linux/&#34;&gt;https://www.howtogeek.com/427805/how-to-use-the-strings-command-on-linux/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;† written with frameworks that will run on Linux&lt;/p&gt;
&lt;p&gt;There is another way to cross compile that involves containers that will be the next post in the podman series!&lt;/p&gt;
</description>
    </item>
    
    
    
    <item>
      <title>Podman: How do I make a new image from a base?</title>
      <link>https://whynotestflight.com/excuses/podman-how-do-i-make-a-new-image-from-a-base/</link>
      <pubDate>Sat, 30 Aug 2025 00:00:00 +0000</pubDate>
      
      <guid>https://whynotestflight.com/excuses/podman-how-do-i-make-a-new-image-from-a-base/</guid>
      <description>&lt;p&gt;So the example image based on httpd that I made is actually a pretty bad image. I manually changed the &lt;code&gt;index.html&lt;/code&gt; file in &lt;code&gt;htdocs/&lt;/code&gt; and &lt;a href=&#34;https://docs.podman.io/en/latest/markdown/podman-commit.1.html&#34;&gt;committed&lt;/a&gt; it directly instead of creating a new project with just the changed files.&lt;/p&gt;
&lt;p&gt;Thankfully the folks offering up the httpd container also offer pretty easy advice on how to extend it.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://hub.docker.com/_/httpd&#34;&gt;https://hub.docker.com/_/httpd&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://www.docker.com/blog/how-to-use-the-apache-httpd-docker-official-image/&#34;&gt;https://www.docker.com/blog/how-to-use-the-apache-httpd-docker-official-image/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/docker-library/httpd&#34;&gt;https://github.com/docker-library/httpd&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Building on that advice, here&amp;rsquo;s a demo:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-shell&#34; data-lang=&#34;shell&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#91d7e3&#34;&gt;cd&lt;/span&gt; ~/to/place/to/store/projects
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;mkdir simple_site
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;mkdir simple_site/public_html
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;touch simple_site/public_html/index.html
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#91d7e3&#34;&gt;echo&lt;/span&gt; -e &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#39;&amp;lt;html&amp;gt;&amp;lt;body&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;    &amp;lt;h1&amp;gt;Hello!&amp;lt;/h1&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;    &amp;lt;p&amp;gt;This is from a containerized project.&amp;lt;/p&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;lt;/body&amp;gt;&amp;lt;/html&amp;gt;&amp;#39;&lt;/span&gt; &amp;gt; simple_site/public_html/index.html
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;touch simple_site/Containerfile
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#91d7e3&#34;&gt;echo&lt;/span&gt; -e &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#39;FROM httpd:2.4
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;COPY public_html /usr/local/apache2/htdocs/&amp;#39;&lt;/span&gt; &amp;gt; simple_site/Containerfile
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;podman build -f simple_site/Containerfile -t my-apache2-demo simple_site
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;podman run -dit -p 8080:80 my-apache2-demo
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;curl localhost:8080
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;the-containerfile&#34;&gt;The Containerfile&lt;/h2&gt;
&lt;p&gt;podman and docker will now both recognize &lt;code&gt;Containerfile&lt;/code&gt; as well as &lt;code&gt;Dockerfile&lt;/code&gt; so in my demo I chose to use &lt;code&gt;Containerfile&lt;/code&gt;.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-Dockerfile&#34; data-lang=&#34;Dockerfile&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;FROM&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;httpd:2.4&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;COPY&lt;/span&gt; ./public-html/ /usr/local/apache2/htdocs/&lt;span style=&#34;color:#ed8796&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;That&amp;rsquo;s crazy simple, but it&amp;rsquo;s on top of &lt;a href=&#34;https://github.com/docker-library/httpd/blob/master/2.4/Dockerfile&#34;&gt;a much more elaborate file&lt;/a&gt; from the base container which includes a call to start running the apache server, i.e. the &lt;a href=&#34;https://stackoverflow.com/questions/59599659/is-cmd-or-entrypoint-necessary-to-mention-in-dockerfile&#34;&gt;required for most cases &lt;code&gt;CMD&lt;/code&gt;&lt;/a&gt; call.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-shell&#34; data-lang=&#34;shell&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;EXPOSE &lt;span style=&#34;color:#f5a97f&#34;&gt;80&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;CMD &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;[&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;httpd-foreground&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;For complete Containerfile/Dockerfile novices here is some video help:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;docker crash course by TechWorld with Nana starting at 49:10 &lt;a href=&#34;https://youtu.be/pg19Z8LL06w?si=hYbiGuqQzW0Zj1KT&amp;amp;t=2950&#34;&gt;https://youtu.be/pg19Z8LL06w?si=hYbiGuqQzW0Zj1KT&amp;amp;t=2950&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;the podman zero to hero video, starting at 22:32 &lt;a href=&#34;https://youtu.be/YXfA5O5Mr18?si=sWsvxCabGD_EkBnf&amp;amp;t=1352&#34;&gt;https://youtu.be/YXfA5O5Mr18?si=sWsvxCabGD_EkBnf&amp;amp;t=1352&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;podman-build&#34;&gt;podman build&lt;/h2&gt;
&lt;p&gt;A new command in that script is &lt;a href=&#34;https://docs.podman.io/en/latest/markdown/podman-build.1.html&#34;&gt;&lt;code&gt;podman build&lt;/code&gt;&lt;/a&gt;, which creates an image and launches a container.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-shell&#34; data-lang=&#34;shell&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;podman build 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# where is the Containerfile relative to the pwd &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;-f simple_site/Containerfile 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# tag (--tag) for the IMAGE that will be created by this build&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# `podman images` will show a localhost/my-apache2-dem&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;-t my-apache2-demo 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## context, what should the working directory be for the commands&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## run in the container file.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;simple_site
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;If the script above had &lt;code&gt;cd&lt;/code&gt;&amp;rsquo;d into &lt;code&gt;simple_site&lt;/code&gt; to run the build command it would have looked like:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-shell&#34; data-lang=&#34;shell&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;podman build -t my-apache2-demo .
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Podman would have found the &lt;code&gt;Containerfile&lt;/code&gt; and the context would be the &lt;code&gt;pwd&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Another alternative would have been to tag it with our local registry and then the new image could be pushed there!&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-shell&#34; data-lang=&#34;shell&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## can tag it even if registry is not available. &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## Registry isn&amp;#39;t verified at the &amp;#34;tag&amp;#34; step.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;podman build -t localhost:5050/my-apache2-demo .
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## make sure its running&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# podman ps -a&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# podman start my_registry # or use ID number&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;podman push localhost:5050/my-apache2-demo
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;If one didn&amp;rsquo;t care about having an image of the build around, from the directory with the Containerfile:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-shell&#34; data-lang=&#34;shell&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;podman build .
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And a nameless image would be created that could be easily removed with &lt;a href=&#34;https://docs.podman.io/en/latest/markdown/podman-image-prune.1.html&#34;&gt;prune&lt;/a&gt; once the container is wound down or by using &lt;a href=&#34;https://docs.podman.io/en/latest/markdown/podman-container-cleanup.1.html#rm&#34;&gt;&lt;code&gt;--rm&lt;/code&gt;&lt;/a&gt; and &lt;a href=&#34;https://docs.podman.io/en/latest/markdown/podman-container-cleanup.1.html#rmi&#34;&gt;&lt;code&gt;--rmi&lt;/code&gt;&lt;/a&gt; in the run command. (also see &lt;a href=&#34;https://docs.podman.io/en/latest/markdown/podman-container-cleanup.1.html#rmi&#34;&gt;podman container cleanup&lt;/a&gt;)&lt;/p&gt;
&lt;h2 id=&#34;the-volume-approach&#34;&gt;The Volume approach&lt;/h2&gt;
&lt;p&gt;The httpd docs point out that one doesn&amp;rsquo;t HAVE to have a Containerfile for such a simple situation. Instead it&amp;rsquo;s possible to just map the files using the &amp;ndash;volume (-v) explored in the previous post.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-shell&#34; data-lang=&#34;shell&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;podman run -dit --name my-apache-app -p 8080:80 -v &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;$PWD&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;:/usr/local/apache2/htdocs/ httpd:2.4
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;There would be no image to push.&lt;/p&gt;
&lt;h2 id=&#34;wrapping-a-binary&#34;&gt;Wrapping a Binary&lt;/h2&gt;
&lt;p&gt;All of this is trying to move me towards understanding the &lt;a href=&#34;https://github.com/apple/swift-container-plugin&#34;&gt;swift-container-plugin&lt;/a&gt; so let&amp;rsquo;s do one more simplistic example, that honestly could have a lot of problems that I&amp;rsquo;m not aware of, but it works.&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s say one has a &lt;a href=&#34;https://en.wikipedia.org/wiki/Static_build&#34;&gt;statically compiled binary&lt;/a&gt; that one knows works on most basic Linux machines.&lt;/p&gt;
&lt;p&gt;I have one that came in at about 197MB (debug build) based on a simple &lt;a href=&#34;http://Hummingbird.codes&#34;&gt;Hummingbird server&lt;/a&gt;. The base code is only slightly edited from an example in the &lt;a href=&#34;https://github.com/apple/swift-container-plugin/tree/main/Examples/HelloWorldHummingbird&#34;&gt;&lt;code&gt;swift-container-plugin&lt;/code&gt; examples&lt;/a&gt; folder.&lt;/p&gt;
&lt;p&gt;Using the &lt;code&gt;swift-container-plugin&lt;/code&gt; I got an image that clocked in at almost 500MB, pressing the limit of my free Digital Ocean account. I want SMALLER.&lt;/p&gt;
&lt;p&gt;So I tried this one and it worked to get an image closer to 200MB. It borrowed heavily from examples in the &lt;a href=&#34;https://github.com/hummingbird-project/hummingbird-examples&#34;&gt;Hummingbird examples repo&lt;/a&gt;, but uses Alpine as the base instead of Ubuntu. Alpine will take the &lt;a href=&#34;https://wiki.musl-libc.org/functional-differences-from-glibc.html&#34;&gt;musl based&lt;/a&gt; binary I built. I also stripped out the build steps and a lot of the niceties. Including some&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-Dockerfile&#34; data-lang=&#34;Dockerfile&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# Most swift examples use Ubuntu. &lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;FROM&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;alpine&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# Create a hummingbird user and group with /app as its home directory&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;RUN&lt;/span&gt; addgroup &lt;span style=&#34;color:#8aadf4&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;&lt;/span&gt;    -S &lt;span style=&#34;color:#8aadf4&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;&lt;/span&gt;    hbGroup &lt;span style=&#34;color:#8aadf4&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;amp;&amp;amp;&lt;/span&gt; adduser &lt;span style=&#34;color:#8aadf4&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;&lt;/span&gt;    -S &lt;span style=&#34;color:#8aadf4&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;&lt;/span&gt;    hbUser &lt;span style=&#34;color:#8aadf4&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;&lt;/span&gt;    -h /app/ &lt;span style=&#34;color:#8aadf4&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;&lt;/span&gt;    -k /dev/null &lt;span style=&#34;color:#8aadf4&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;&lt;/span&gt;    -G hbGroup&lt;span style=&#34;color:#ed8796&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# Switch to the new home directory&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;WORKDIR&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;/app&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# give the binary to the hummingbird user&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;COPY&lt;/span&gt; --chown&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt;hbUser:hbGroup ./binary /app/&lt;span style=&#34;color:#ed8796&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# Ensure all further commands run as the hummingbird user&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;USER&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;hbUser:hbGroup&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# Let Docker bind to port 8080&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;EXPOSE&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;8080&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# Start the Hummingbird service when the image is run, default to listening on 8080 in production environment&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;ENTRYPOINT&lt;/span&gt; [&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;./hello-world&amp;#34;&lt;/span&gt;]&lt;span style=&#34;color:#ed8796&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;CMD&lt;/span&gt; [&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;--hostname&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;0.0.0.0&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;--port&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;8080&amp;#34;&lt;/span&gt;]&lt;span style=&#34;color:#ed8796&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The following script assumes the binary for &lt;code&gt;HelloServer&lt;/code&gt; has already been cross-compiled, which I&amp;rsquo;ll cover in a different post.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-shell&#34; data-lang=&#34;shell&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#91d7e3&#34;&gt;cd&lt;/span&gt; ~/to/place/to/store/projects
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;mkdir -p HelloWrapper
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;mkdir -p HelloWrapper/binary
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;cp HelloServer/.build/x86_64-swift-linux-musl/debug/hello-world HelloWrapper/binary/hello-world
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;touch HelloWrapper/Containerfile
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# add contents to containerfile&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#91d7e3&#34;&gt;cd&lt;/span&gt; HelloWrapper
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;podman build -t hellowrapper .
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;podman run -d -p 8080:8080 localhost/hellowrapper
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;curl localhost:8080
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;podman images
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;podman image inspect localhost/hellowrapper
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;That last &amp;ldquo;inspect&amp;rdquo; command is new, &lt;a href=&#34;https://docs.podman.io/en/latest/markdown/podman-inspect.1.html&#34;&gt;podman inspect&lt;/a&gt; provides a number of detains about the entities podman manages: containers, images, volumes, network, pods. One can limit it by providing a subtype. In this case images with &lt;a href=&#34;https://docs.podman.io/en/latest/markdown/podman-image-inspect.1.html&#34;&gt;podman image inspect&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&#34;summary&#34;&gt;Summary&lt;/h2&gt;
&lt;p&gt;These were two VERY basic &lt;code&gt;Containerfiles&lt;/code&gt; that would need improvement before going into production&amp;hellip; but they work! Improving them and actually getting the site up on Digital Ocean is part of the next few posts. One avenue to investigate is starting from the base &lt;a href=&#34;https://hub.docker.com/_/scratch/&#34;&gt;scratch&lt;/a&gt; (&lt;a href=&#34;https://forums.swift.org/t/de-minimis-server-containerfile-for-a-musl-based-static-linking/81887/2&#34;&gt;Thanks jheck!&lt;/a&gt;)&lt;/p&gt;
&lt;h2 id=&#34;appendix-the-swift-code&#34;&gt;Appendix: The Swift Code&lt;/h2&gt;
&lt;p&gt;For posterity the swift code. Again this code it largely identical to:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/apple/swift-container-plugin/tree/main/Examples/HelloWorldHummingbird&#34;&gt;https://github.com/apple/swift-container-plugin/tree/main/Examples/HelloWorldHummingbird&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Which is Apache-2.0&amp;rsquo;d to Apple Inc. and the SwiftContainerPlugin project authors.&lt;/p&gt;
&lt;h3 id=&#34;packageswift&#34;&gt;Package.swift&lt;/h3&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;PackageDescription&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;package&lt;/span&gt; = Package(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    name: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;hello-world&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    platforms: [.macOS(.v14)],
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    dependencies: [
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        .package(url: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;https://github.com/hummingbird-project/hummingbird.git&amp;#34;&lt;/span&gt;, from: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;2.1.0&amp;#34;&lt;/span&gt;),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// This was here from when the example was just a main.swift?&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// .package(path: &amp;#34;../..&amp;#34;),&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        .package(url: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;https://github.com/apple/swift-argument-parser&amp;#34;&lt;/span&gt;, from: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;1.3.0&amp;#34;&lt;/span&gt;),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        .package(url: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;https://github.com/apple/swift-container-plugin&amp;#34;&lt;/span&gt;, from: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;1.0.0&amp;#34;&lt;/span&gt;),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    ],
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    targets: [
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        .executableTarget(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            name: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;hello-world&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            dependencies: [
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                .product(name: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Hummingbird&amp;#34;&lt;/span&gt;, package: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;hummingbird&amp;#34;&lt;/span&gt;),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                .product(name: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;ArgumentParser&amp;#34;&lt;/span&gt;, package: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;swift-argument-parser&amp;#34;&lt;/span&gt;),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            ]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        )
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    ]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;appswift&#34;&gt;App.swift&lt;/h3&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;ArgumentParser&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;@main
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;Hello&lt;/span&gt;: AsyncParsableCommand {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    @Option(name: .shortAndLong)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;hostname&lt;/span&gt;: &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt; = &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;0.0.0.0&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    @Option(name: .shortAndLong)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;port&lt;/span&gt;: &lt;span style=&#34;color:#91d7e3&#34;&gt;Int&lt;/span&gt; = &lt;span style=&#34;color:#f5a97f&#34;&gt;8080&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;run&lt;/span&gt;() async &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;app&lt;/span&gt; = buildApplication(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            configuration: .&lt;span style=&#34;color:#ed8796&#34;&gt;init&lt;/span&gt;(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                address: .hostname(hostname, port: port),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                serverName: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;HelloServer&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            )
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        )
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; await app.runService()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;applicationbuildswift&#34;&gt;Application+build.swift&lt;/h3&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;Foundation&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;Hummingbird&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;Logging&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;myos&lt;/span&gt; = ProcessInfo.processInfo.operatingSystemVersionString
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;buildApplication&lt;/span&gt;(configuration: ApplicationConfiguration) -&amp;gt; some ApplicationProtocol {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;router&lt;/span&gt; = Router()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    router.addMiddleware { LogRequestsMiddleware(.info) }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    router.&lt;span style=&#34;color:#c6a0f6&#34;&gt;get&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;/&amp;#34;&lt;/span&gt;) { &lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt;, &lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Hello World, from Hummingbird on &lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;myos&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\n&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;app&lt;/span&gt; = Application(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        router: router,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        configuration: configuration,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        logger: Logger(label: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;HelloWorldHummingbird&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    )
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; app
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description>
    </item>
    
    
    
    <item>
      <title>Podman: How do I preserve or share my image?</title>
      <link>https://whynotestflight.com/excuses/podman-how-do-i-preserve-or-share-my-image/</link>
      <pubDate>Fri, 29 Aug 2025 00:00:00 +0000</pubDate>
      
      <guid>https://whynotestflight.com/excuses/podman-how-do-i-preserve-or-share-my-image/</guid>
      <description>&lt;h2 id=&#34;vocabulary-overview&#34;&gt;Vocabulary Overview&lt;/h2&gt;
&lt;p&gt;When talking about moving things it helps to be clear about what is being moved and to what kind of place.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;registry&lt;/strong&gt;: a service that stores images&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;repository&lt;/strong&gt;: a collection of related images (same name, different tags)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;image&lt;/strong&gt;: a recipe and resources to build a container&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;container&lt;/strong&gt;: an instance of an image, fully assembled and prepared&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;ID&lt;/strong&gt;: both containers and images get giant hashes to identify themselves, like git commits.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;name&lt;/strong&gt;: a human readable name for a container or image. the word on the street is that images are okay to name, but containers shouldn&amp;rsquo;t be because there may be lots of them in a shared environment and if everyone goes around trying to use the label &amp;ldquo;my_container&amp;rdquo;, it will get ugly.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;artifact&lt;/strong&gt;: &lt;a href=&#34;https://oras.land/docs/&#34;&gt;supplemental material/non-container material&lt;/a&gt; it makes sense to try to store in a registry along with images&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;tag&lt;/strong&gt;: like a git tag, a label for a version. they can be mutable or &lt;a href=&#34;https://docs.gitlab.com/user/packages/container_registry/immutable_container_tags/&#34;&gt;immutable&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Tags were what I needed clarified the most. One already showed up when doing a pull. It&amp;rsquo;s the &lt;code&gt;:latest&lt;/code&gt;. &lt;code&gt;latest&lt;/code&gt; is the default when nothing is specified as well.&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;podman pull docker.io/library/httpd:latest 
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;I suspected that like with &lt;a href=&#34;https://git-scm.com/book/en/v2/Git-Basics-Tagging&#34;&gt;git tags&lt;/a&gt; there&amp;rsquo;d be conventions around their usage so here is some reading:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://stackoverflow.com/questions/35000484/how-to-tag-a-docker-container#35000818&#34;&gt;https://stackoverflow.com/questions/35000484/how-to-tag-a-docker-container#35000818&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://docs.redhat.com/en/documentation/openshift_container_platform/3.11/html/developer_guide/dev-guide-managing-images&#34;&gt;https://docs.redhat.com/en/documentation/openshift_container_platform/3.11/html/developer_guide/dev-guide-managing-images&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://thelinuxcode.com/a-quick-introduction-to-docker-tags/&#34;&gt;https://thelinuxcode.com/a-quick-introduction-to-docker-tags/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://commandmasters.com/commands/docker-tag-common/&#34;&gt;https://commandmasters.com/commands/docker-tag-common/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://medium.com/@laura_67852/docker-tags-demystified-a-guide-with-examples-6c76b381068d&#34;&gt;https://medium.com/@laura_67852/docker-tags-demystified-a-guide-with-examples-6c76b381068d&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;make-sure-theres-an-image-to-work-with&#34;&gt;Make Sure There&amp;rsquo;s an Image to Work With&lt;/h2&gt;
&lt;p&gt;So imagine needing to reinit the Mac&amp;rsquo;s podman VM.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-shell&#34; data-lang=&#34;shell&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;podman machine stop
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;podman machine rm
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;podman machine init
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;podman machine start
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;podman images
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;On the start up there&amp;rsquo;d be no images! Including the new template! How to keep it around even if the podman VM gets wiped? How to share one once it&amp;rsquo;s ready?&lt;/p&gt;
&lt;p&gt;First, recreate it:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-shell&#34; data-lang=&#34;shell&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# docker login #if needed&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;podman pull docker.io/library/httpd:latest &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# login required!&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;podman run -dt -p 8080:80/tcp docker.io/library/httpd
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;podman ps
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;podman &lt;span style=&#34;color:#91d7e3&#34;&gt;exec&lt;/span&gt; -it &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;{&lt;/span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;$CONTAINER_ID&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;}&lt;/span&gt; bash
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;:/usr/local/apache2# &amp;gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;echo&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#39;&amp;lt;html&amp;gt;&amp;lt;body&amp;gt;&amp;lt;h1&amp;gt;Still works!&amp;lt;/h1&amp;gt;&amp;lt;/body&amp;gt;&amp;lt;/html&amp;gt;&amp;#39;&lt;/span&gt; &amp;gt; htdocs/index.html
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;:/usr/local/apache2# &amp;gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;exit&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;curl localhost:8080
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;podman commit &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;{&lt;/span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;$CONTAINER_ID&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;}&lt;/span&gt; my-httpd-template
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;podman images
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# podman image rm {$CONTAINER_ID} ## to delete&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;option-1-save-to-an-archive&#34;&gt;Option 1: Save to an archive&lt;/h2&gt;
&lt;p&gt;First option to preserve the image even if we delete &lt;code&gt;podman machine&lt;/code&gt; again is to use the save command that takes an output on the host mac.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-shell&#34; data-lang=&#34;shell&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;podman save --output httpd_template_image.tar localhost/my-httpd-template
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;saves a copy of the image (or &lt;em&gt;images&lt;/em&gt; if desired) to an archive file called httpd_template_image.tar in the pwd using &lt;a href=&#34;https://docs.podman.io/en/latest/markdown/podman-save.1.html&#34;&gt;save&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;One could load it back into podman with &lt;a href=&#34;https://docs.podman.io/en/latest/markdown/podman-load.1.html&#34;&gt;load&lt;/a&gt;&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-shell&#34; data-lang=&#34;shell&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;podman load --input httpd_template_image.tar
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;option-2-export-is-for-containers&#34;&gt;Option 2: Export is for Containers&lt;/h2&gt;
&lt;p&gt;&lt;a href=&#34;https://docs.podman.io/en/latest/markdown/podman-export.1.html&#34;&gt;Export&lt;/a&gt; is similar to &lt;code&gt;save&lt;/code&gt;, but for use on containers, not images. Using &lt;a href=&#34;https://docs.podman.io/en/latest/markdown/podman-import.1.html&#34;&gt;import&lt;/a&gt; takes that export archive of a container and will bring it in as an image.&lt;/p&gt;
&lt;p&gt;So if we really wanted to we could have used it on our changed httpd container rather than commit the container to an new image.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-shell&#34; data-lang=&#34;shell&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## will create tar file in pwd&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;podman &lt;span style=&#34;color:#91d7e3&#34;&gt;export&lt;/span&gt; --output changed_httpd_container.tar &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;{&lt;/span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;$CONTAINER_ID&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;podman import changed_httpd_container.tar imported-httpd-image
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;option-3-podman-push-dir--podman-cp&#34;&gt;Option 3: podman push :dir / podman cp&lt;/h2&gt;
&lt;p&gt;If one just wanted to move the folder around the &lt;code&gt;podman machine&lt;/code&gt; one could pretty easily get a copy using &lt;a href=&#34;https://docs.podman.io/en/latest/markdown/podman-push.1.html&#34;&gt;push&lt;/a&gt; just to another directory. &lt;code&gt;push :dir&lt;/code&gt; is only for moving items within the same machine.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-shell&#34; data-lang=&#34;shell&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;podman machine ssh
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;core@localhost:~ mkdir -p ~/container_tmp
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# podman-machine-default has podman installed too! &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;core@localhost:~ podman push my-httpd-template dir:/Users/&lt;span style=&#34;color:#f4dbd6&#34;&gt;$USER&lt;/span&gt;/container_tmp/my-httpd-template
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;core@localhost:~ ls container_tmp/
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This DOES NOT get the files out of &lt;code&gt;podman-machine-default&lt;/code&gt;. &lt;code&gt;/Users/$USER/container_tmp/&lt;/code&gt; is still on the VM. To move the files to the host machine use &lt;a href=&#34;https://docs.podman.io/en/latest/markdown/podman-machine-cp.1.html&#34;&gt;podman machine cp&lt;/a&gt; from the host mac.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-shell&#34; data-lang=&#34;shell&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# this moves the folder we just created with the push. &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;podman machine cp podman-machine-default:/var/home/core/container_tmp/my-httpd-template ~/saved_containers/my-httpd-template
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This is different than &lt;a href=&#34;https://docs.podman.io/en/latest/markdown/podman-cp.1.html&#34;&gt;podman cp&lt;/a&gt;, which is for copying to, from and between containers. That page also provides &lt;a href=&#34;https://docs.podman.io/en/latest/markdown/podman-cp.1.html#alternatives&#34;&gt;alternatives&lt;/a&gt; to itself for moving files around containers.&lt;/p&gt;
&lt;h2 id=&#34;option-4-using-push-to-a-remote-registry&#34;&gt;Option 4: Using push to a remote registry.&lt;/h2&gt;
&lt;p&gt;Rather than just keeping a hand-tooled local backup, the more usual would be to push useful images up to a registry. I am going to show two. Docker Hub and Digital Ocean.&lt;/p&gt;
&lt;h3 id=&#34;docker-hub&#34;&gt;Docker Hub&lt;/h3&gt;
&lt;p&gt;If you&amp;rsquo;ve followed along, you have a login solution because it was required to get the image, but see the end of this section for more info.&lt;/p&gt;
&lt;p&gt;One can create a new repository Docker Hub&amp;rsquo;s repository home page:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;https://hub.docker.com/repository/create?namespace=$DOCKER_USERNAME&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Notice I am saying repository. The registry is docker hub. Each project gets a repository for all its versions.&lt;/p&gt;
&lt;p&gt;Instead of creating one from the web-gui, I pulled out the CLI directions.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-shell&#34; data-lang=&#34;shell&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;docker tag local-image:tagname new-repo:tagname
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;docker push new-repo:tagname
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This translates to podman as:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-shell&#34; data-lang=&#34;shell&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;podman tag localhost/my-httpd-template docker.io/&lt;span style=&#34;color:#f4dbd6&#34;&gt;$DOCKER_USERNAME&lt;/span&gt;/my-httpd-template:v1
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;podman images &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#optional. see the new image (it&amp;#39;s still only local)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;podman push docker.io/&lt;span style=&#34;color:#f4dbd6&#34;&gt;$DOCKER_USERNAME&lt;/span&gt;/my-httpd-template:v1
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This exact repository can be seen for now at:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://hub.docker.com/repository/docker/carlynorama/my-httpd-template/&#34;&gt;https://hub.docker.com/repository/docker/carlynorama/my-httpd-template/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&#34;a-reminder-about-logging-in&#34;&gt;A reminder about logging in:&lt;/h4&gt;
&lt;p&gt;Option A (&lt;a href=&#34;https://docs.docker.com/reference/cli/docker/login/&#34;&gt;docker login&lt;/a&gt;):&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-shell&#34; data-lang=&#34;shell&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;docker login
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Option B (&lt;a href=&#34;https://docs.podman.io/en/latest/markdown/podman-login.1.html&#34;&gt;podman login&lt;/a&gt;):&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-shell&#34; data-lang=&#34;shell&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;podman login docker.io
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Username: &lt;span style=&#34;color:#f4dbd6&#34;&gt;$DOCKER_USERNAME&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Password: 
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Note: if the expected password for a service doesn&amp;rsquo;t work, try an API key.&lt;/p&gt;
&lt;h3 id=&#34;digital-ocean&#34;&gt;Digital Ocean&lt;/h3&gt;
&lt;p&gt;Create a &lt;a href=&#34;https://www.digitalocean.com/products/container-registry&#34;&gt;container registry&lt;/a&gt;. There is a free version that allows for 1 and only 1 repository, but that&amp;rsquo;s okay for this. (&lt;a href=&#34;https://m.do.co/c/2a910cd4cd9f&#34;&gt;affiliate link&lt;/a&gt; with some free credits if useful.)&lt;/p&gt;
&lt;p&gt;The steps walk through the process of &lt;a href=&#34;https://docs.digitalocean.com/reference/doctl/how-to/install/&#34;&gt;installing THEIR cli&lt;/a&gt; and link to how to create an &lt;a href=&#34;https://cloud.digitalocean.com/account/api/tokens/&#34;&gt;API token&lt;/a&gt; as needed. DO NOT LOOSE IT. (Passwords, BitWarden, LastPass, 1Password, Encrypted Note, Keychain Secure Note&amp;hellip; something.)&lt;/p&gt;
&lt;p&gt;As a note on Digital Ocean, I used to unreservedly recommend them because they put so much work into high quality documentation that covered topics in general, not just how to do things on their platform. It was a real differentiator. Made me willing to pay a premium to support the public good they provided. Back in 2023 they laid off a bunch of those folks, changed their docs home page and blog topics to be more DO specific and leaned into AI&amp;hellip; so &lt;code&gt;¯\_ (ツ)_/¯&lt;/code&gt;. At least they still seems to have straight forward pricing models that prevent surprises.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://docs.digitalocean.com/products/container-registry/getting-started/quickstart/&#34;&gt;https://docs.digitalocean.com/products/container-registry/getting-started/quickstart/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://docs.digitalocean.com/products/container-registry/how-to/use-registry-docker-kubernetes/&#34;&gt;https://docs.digitalocean.com/products/container-registry/how-to/use-registry-docker-kubernetes/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;logging-in&#34;&gt;Logging in&lt;/h3&gt;
&lt;p&gt;One can either login through the digital ocean CLI, registering the API key with Docker directly, or the podman login process.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-shell&#34; data-lang=&#34;shell&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## Option A&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;doctl registry login
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## Option B&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;docker login registry.digitalocean.com
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#&amp;gt; Username: &amp;lt;registered-email&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#&amp;gt; Password: &amp;lt;paste-api-token&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## Option C&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;podman login registry.digitalocean.com
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#&amp;gt; Username: &amp;lt;registered-email&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#&amp;gt; Password: &amp;lt;paste-api-token&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;push-to-digital-ocean&#34;&gt;push to Digital Ocean&lt;/h3&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-shell&#34; data-lang=&#34;shell&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# LOGIN FIRST&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;podman tag localhost/my-httpd-template registry.digitalocean.com/&lt;span style=&#34;color:#f4dbd6&#34;&gt;$DO_REGISTRY_NAME&lt;/span&gt;/my-httpd-template:v1
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;podman images &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#optional. see the new image (it&amp;#39;s still only local)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;podman push registry.digitalocean.com/&lt;span style=&#34;color:#f4dbd6&#34;&gt;$DO_REGISTRY_NAME&lt;/span&gt;/my-httpd-template:v1
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This one is PRIVATE, so I can&amp;rsquo;t provide a link. It uses 45.65 MB / 500 MB of my space. YIKES. That&amp;rsquo;s a lot for one wee little web page. But its storing the whole server profile, so it won&amp;rsquo;t get much bigger than that as more content gets added.&lt;/p&gt;
&lt;h2 id=&#34;option-5-a-local-registry&#34;&gt;Option 5: A local registry&lt;/h2&gt;
&lt;p&gt;Sometimes one wants a registry on ones own machine or for the local network. For testing, for privacy, for control, for bandwidth. Many reasons. The examples I found were for Linux machines, and there are a couple of gotcha&amp;rsquo;s porting them to Mac.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://distribution.github.io/distribution/&#34;&gt;https://distribution.github.io/distribution/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://golangexpert.com/blog/devops/podman-local-registry&#34;&gt;https://golangexpert.com/blog/devops/podman-local-registry&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://bradleybattista.substack.com/p/setting-up-a-podman-local-image-registry&#34;&gt;https://bradleybattista.substack.com/p/setting-up-a-podman-local-image-registry&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://infotechys.com/host-your-own-podman-registry/#elementor-toc__heading-anchor-3&#34;&gt;https://infotechys.com/host-your-own-podman-registry/#elementor-toc__heading-anchor-3&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://distribution.github.io/distribution/about/deploying/&#34;&gt;https://distribution.github.io/distribution/about/deploying/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://thenewstack.io/tutorial-host-a-local-podman-image-registry/&#34;&gt;https://thenewstack.io/tutorial-host-a-local-podman-image-registry/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/devops2029/podman/blob/main/How%20to%20set%20up%20a%20local%20image%20repository%20with%20Podman&#34;&gt;https://github.com/devops2029/podman/blob/main/How%20to%20set%20up%20a%20local%20image%20repository%20with%20Podman&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The TL;DR&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-shell&#34; data-lang=&#34;shell&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## Make the storage folder&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;mkdir -p ~/web_tools/registry
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## pull and run the registry image from docker using that folder&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## configured to use the folder we want and the port we want. &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;podman run -d --name my_registry -p 5050:5000 -v /Users/&lt;span style=&#34;color:#f4dbd6&#34;&gt;$USER&lt;/span&gt;/web_tools/registry:/var/lib/registry --restart&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt;always registry:latest
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## tag the image over to the new registry port&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;podman tag localhost/my-httpd-template localhost:5050/my-httpd-template
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## see that no files are there yet&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ls ~/web_tools/registry
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## push to the registry&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;podman push localhost:5050/my-httpd-template --tls-verify&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#91d7e3&#34;&gt;false&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## see the files are there now.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ls ~/web_tools/registry/docker/registry/v2/repositories/my-httpd-template
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## Remove all the local versions&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## See all the current images, some of mine had the same ID&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## b/c of how I pushed to the remotes&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;podman images
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## remove all the images with my-httpd-template in the name&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;podman image rm localhost:5050/my-httpd-template
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;podman image rm localhost/my-httpd-template
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;podman image rm -f &lt;span style=&#34;color:#f4dbd6&#34;&gt;$MY_DUPLICATED_ID&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## should see no my-httpd-template&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;podman images
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## make is so don&amp;#39;t have to use --tls-verify=false every time and so its contents will appear in searches&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## see the search without the registry&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;podman search my-httpd-template
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;podman machine ssh
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## On the VM change the registries.conf in the local folder. &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## WARNING: this command will overwrite anything that is currently in it. &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;core@localhost:~ &lt;span style=&#34;color:#91d7e3&#34;&gt;echo&lt;/span&gt; -e &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#39;unqualified-search-registries = [&amp;#34;localhost:5050&amp;#34;, &amp;#34;docker.io&amp;#34;, &amp;#34;ghrc.io&amp;#34;, &amp;#34;quay.io&amp;#34;, &amp;#34;registry.fedoraproject.org&amp;#34;]\n\n[[registry]]\nlocation=&amp;#34;localhost:5050&amp;#34;\ninsecure=true&amp;#39;&lt;/span&gt; &amp;gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;$HOME&lt;/span&gt;/.config/containers/registries.conf
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;core@localhost:~ &lt;span style=&#34;color:#91d7e3&#34;&gt;exit&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## see the search with our local registry in the results&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;podman search my-httpd-template
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## and pull from the local!&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;podman pull localhost:5050/my-httpd-template
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## the image is back&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;podman images
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;When trying to figure out what all those commands should be there are four questions have to be answered:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;where will the files be stored?&lt;/li&gt;
&lt;li&gt;where is it going to be served to?&lt;/li&gt;
&lt;li&gt;what tool is going to serve it?&lt;/li&gt;
&lt;li&gt;how will podman know to look in it?&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;where-will-the-files-be-stored&#34;&gt;Where will the files be stored?&lt;/h3&gt;
&lt;p&gt;The the files question can be easy to answer. I&amp;rsquo;m going to create a folder on the mac at &lt;code&gt;/Users/$USER&lt;/code&gt; to start.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-shell&#34; data-lang=&#34;shell&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;mkdir -p ~/web_tools/registry
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The expected location for registry files is &lt;code&gt;/var/lib/registry&lt;/code&gt;, and one could create that inside &lt;code&gt;podman machine&lt;/code&gt; and set up a volume to use that instead, but for me the point is to have the registry saved to my user on the host mac.&lt;/p&gt;
&lt;h3 id=&#34;where-is-it-going-to-be-served-to&#34;&gt;Where is it going to be served to?&lt;/h3&gt;
&lt;p&gt;All the examples use port 5000 on both the host and the container. But on a Mac that&amp;rsquo;s &lt;a href=&#34;https://developer.apple.com/forums/thread/777326&#34;&gt;typically in use&lt;/a&gt; (along with 7000) by the Control Center. To free it up one needs to &lt;a href=&#34;https://apple.stackexchange.com/questions/431154/should-controlcenter-app-listen-to-port-5000-tcp-on-a-normal-macos-monterey-syst&#34;&gt;turn off&lt;/a&gt; Continuity, AirPlay&amp;hellip; things I like using.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-shell&#34; data-lang=&#34;shell&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## See whose on your port&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;lsof -n -P -i :5000
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## Dig further:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;lsof -i
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;sudo skywalkctl flow -n -P &lt;span style=&#34;color:#f4dbd6&#34;&gt;$PID_CONTROL_CENTER&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;sudo skywalkctl netstat -a
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;So I am going to use a different port in this example. The nice thing is the container will still be able to use the default port (5000). This does mean when using the registry we will sometimes need to specify the port for software that would otherwise look for the default.&lt;/p&gt;
&lt;h3 id=&#34;what-tool-is-going-to-serve-it&#34;&gt;What tool is going to serve it?&lt;/h3&gt;
&lt;p&gt;The answer is to have &lt;code&gt;podman&lt;/code&gt; run an existing &lt;a href=&#34;https://hub.docker.com/_/registry&#34;&gt;registry image&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;But how to give podman access to the folder and the port? We&amp;rsquo;re going to need to use some flags.&lt;/p&gt;
&lt;h4 id=&#34;volume&#34;&gt;volume&lt;/h4&gt;
&lt;p&gt;&lt;code&gt;[[SOURCE-VOLUME|HOST-DIR:]CONTAINER-DIR[:OPTIONS]]&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;How will podman know about the folder? Because it will be mapped to a volume.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://blog.christophersmart.com/2021/01/31/volumes-and-rootless-podman/&#34;&gt;https://blog.christophersmart.com/2021/01/31/volumes-and-rootless-podman/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://docs.podman.io/en/latest/markdown/podman-run.1.html#volume-v-source-volume-host-dir-container-dir-options&#34;&gt;https://docs.podman.io/en/latest/markdown/podman-run.1.html#volume-v-source-volume-host-dir-container-dir-options&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://docs.podman.io/en/latest/markdown/podman-volume.1.html&#34;&gt;https://docs.podman.io/en/latest/markdown/podman-volume.1.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://www.redhat.com/en/blog/debug-rootless-podman-mounted-volumes&#34;&gt;https://www.redhat.com/en/blog/debug-rootless-podman-mounted-volumes&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;One can create a volume in a separate step or at the time of container creation. At the time of container creation means the &lt;code&gt;run&lt;/code&gt; command will handle all the appropriate configuration.&lt;/p&gt;
&lt;p&gt;If one calls the command to run (and also pull if not already on the machine) a &lt;a href=&#34;https://www.docker.com/blog/use-cases-and-tips-for-using-the-busybox-docker-official-image/&#34;&gt;busybox&lt;/a&gt; image in one step:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-shell&#34; data-lang=&#34;shell&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;podman run -dit --volume src:/dest busybox
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;and no volume called &lt;code&gt;src&lt;/code&gt; already exists podman will create it on the podman vm at&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-shell&#34; data-lang=&#34;shell&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;/var/home/core/.local/share/containers/storage/volumes/src
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The &lt;code&gt;/dest&lt;/code&gt; part is where it maps to &lt;em&gt;on the container&amp;rsquo;s&lt;/em&gt; file structure.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-shell&#34; data-lang=&#34;shell&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;podman ps &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#to get the container id if didn&amp;#39;t nab it. &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;podman &lt;span style=&#34;color:#91d7e3&#34;&gt;exec&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;$BUSYBOX_CONTAINER_ID&lt;/span&gt; ls -ld /dest
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;podman &lt;span style=&#34;color:#91d7e3&#34;&gt;exec&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;$BUSYBOX_CONTAINER_ID&lt;/span&gt; touch hello.txt
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;podman machine ssh
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;core@localhost:~$ ls -la /var/home/core/.local/share/containers/storage/volumes/
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;NOTE: &lt;code&gt;busybox&lt;/code&gt; can be used in the &lt;code&gt;run&lt;/code&gt; command without &lt;code&gt;docker.io/busybox&lt;/code&gt; because &lt;code&gt;docker.io&lt;/code&gt; is one of the &lt;a href=&#34;https://stackoverflow.com/a/78949200&#34;&gt;unqualified hosts&lt;/a&gt; in both the default registries.conf and the one updated in the last post. &lt;a href=&#34;https://docs.redhat.com/en/documentation/red_hat_enterprise_linux/9/html/building_running_and_managing_containers/working-with-container-registries_building-running-and-managing-containers&#34;&gt;more&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;To do something a little more useful, where the source folder is accessible by the mac user, one can either set up a volume ahead of time or just pass in an actual path to an existing directory. While the folder for the SOURCE side must exist before hand, the one on the DESTINATION side does not. If it doesn&amp;rsquo;t exist it will be created as part of the container&amp;rsquo;s start up.&lt;/p&gt;
&lt;p&gt;NOTE: the following commands will open an interactive shell immediately to help with testing file creation (&lt;code&gt;-it&lt;/code&gt; without the &lt;code&gt;d&lt;/code&gt;).  The &lt;code&gt;pwd&lt;/code&gt; will be &lt;code&gt;/&lt;/code&gt;, not &lt;code&gt;/var/home/core/&lt;/code&gt; like with &lt;code&gt;podman machine ssh&lt;/code&gt;.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-shell&#34; data-lang=&#34;shell&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;mkdir -p ~/my_demo_volume_a
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;touch ~/my_demo_volume_a/waiting_to_be_seen.txt
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;podman run -it --rm --volume ~/my_demo_volume_a:/dest busybox
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# / # cd /dest&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# / # ls&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# / # touch hello_a.txt&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# / # exit&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Or the long way. &lt;a href=&#34;https://github.com/containers/podman/issues/12013#issuecomment-1017998512&#34;&gt;See discussion on this github issue&lt;/a&gt;&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-shell&#34; data-lang=&#34;shell&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;mkdir -p ~/my_demo_volume_b
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## Look at how much has to be specified!!!&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;podman volume create --driver &lt;span style=&#34;color:#91d7e3&#34;&gt;local&lt;/span&gt; --opt &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#39;type=none&amp;#39;&lt;/span&gt; --opt &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;device=/Users/&lt;/span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;$USER&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;/my_demo_volume_b&amp;#34;&lt;/span&gt; --opt &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#39;o=bind&amp;#39;&lt;/span&gt; my_fancy_volume
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;podman run -it --rm --volume my_fancy_volume:/dest busybox
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The volumes created by &lt;code&gt;run&lt;/code&gt; where the source is a directory path do not show up in &lt;code&gt;podman volume ls&lt;/code&gt;, only named ones do.&lt;/p&gt;
&lt;p&gt;There is an alternate syntax for options with a colon after the destination parameter followed by comma separated options. A common one to see is &lt;a href=&#34;https://unix.stackexchange.com/questions/651198/podman-volume-mounts-when-to-use-the-z-or-z-suffix&#34;&gt;z or Z&lt;/a&gt;. They seem to largely handle permission issues. Try letting &lt;code&gt;run&lt;/code&gt; handle your situation before mucking about with them.&lt;/p&gt;
&lt;h4 id=&#34;publish&#34;&gt;publish&lt;/h4&gt;
&lt;p&gt;&lt;code&gt;[[ip:][hostPort]:]containerPort[/protocol]&lt;/code&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://docs.podman.io/en/stable/markdown/podman-run.1.html#publish-p-ip-hostport-containerport-ip-containerport-hostport-containerport-containerport&#34;&gt;https://docs.podman.io/en/stable/markdown/podman-run.1.html#publish-p-ip-hostport-containerport-ip-containerport-hostport-containerport-containerport&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/containers/podman/blob/main/docs/tutorials/basic_networking.md&#34;&gt;https://github.com/containers/podman/blob/main/docs/tutorials/basic_networking.md&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://www.redhat.com/en/blog/container-networking-podman&#34;&gt;https://www.redhat.com/en/blog/container-networking-podman&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://www.geeksforgeeks.org/devops/configuring-container-networking-with-podman/&#34;&gt;https://www.geeksforgeeks.org/devops/configuring-container-networking-with-podman/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In a run command, &lt;code&gt;-p&lt;/code&gt; isn&amp;rsquo;t actually short for &amp;ldquo;port&amp;rdquo; but &lt;a href=&#34;https://docs.podman.io/en/stable/markdown/podman-run.1.html#publish-p-ip-hostport-containerport-protocol&#34;&gt;publish&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The registry will need to be available on the network since that&amp;rsquo;s what all the tooling expects. The &lt;code&gt;publish&lt;/code&gt; option can map a single port or a range of ports. If a container has a lot of ports to expose, &lt;a href=&#34;https://docs.podman.io/en/stable/markdown/podman-run.1.html#publish-all-p-true-false&#34;&gt;&lt;code&gt;--publish-all, -P&lt;/code&gt;&lt;/a&gt; will map random host ports as needed. One can see the ports being used with &lt;a href=&#34;https://docs.podman.io/en/stable/markdown/podman-port.1.html&#34;&gt;podman ports&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;my-httpd-template&lt;/code&gt; needed this option itself!&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-shell&#34; data-lang=&#34;shell&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;podman run -dt -p 8080:80/tcp localhost/my-httpd-template
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Alternatives might have looked like:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-shell&#34; data-lang=&#34;shell&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# will only respond on 127.0.0.1, not all IPs (double check etc/hosts)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;podman run -dt -p localhost:8080:80/tcp localhost/my-httpd-template
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# to get a random available port. &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;podman run -dt -p localhost::80/tcp localhost/my-httpd-template
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# uses tcp by default&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;podman run -dt -p 8080:80 localhost/my-httpd-template
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# use udp, scpt is the other option. To use more than one, -p for each.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;podman run -dt -p 8080:80/udp localhost/my-httpd-template
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h4 id=&#34;restart&#34;&gt;restart&lt;/h4&gt;
&lt;p&gt;&lt;code&gt;--restart=policy&lt;/code&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://docs.podman.io/en/latest/markdown/podman-run.1.html#restart-policy&#34;&gt;https://docs.podman.io/en/latest/markdown/podman-run.1.html#restart-policy&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;From the docs, valid policy values are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;no&lt;/code&gt; : Do not restart containers on exit&lt;/li&gt;
&lt;li&gt;&lt;code&gt;never&lt;/code&gt; : Synonym for no; do not restart containers on exit&lt;/li&gt;
&lt;li&gt;&lt;code&gt;on-failure[:max_retries]&lt;/code&gt; : Restart containers when they exit with a - non-zero exit code, retrying indefinitely or until the optional max_retries count is hit&lt;/li&gt;
&lt;li&gt;&lt;code&gt;always&lt;/code&gt; : Restart containers when they exit, regardless of status, retrying indefinitely&lt;/li&gt;
&lt;li&gt;&lt;code&gt;unless-stopped&lt;/code&gt; : Identical to always&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Our registry will use &amp;ldquo;always&amp;rdquo;, but keep in mind &amp;ldquo;Restart policy does not take effect if a container is stopped via the podman kill or podman stop commands.&amp;rdquo; (also from doc link.)&lt;/p&gt;
&lt;h4 id=&#34;privileged&#34;&gt;privileged&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://docs.podman.io/en/latest/markdown/podman-run.1.html#privileged&#34;&gt;https://docs.podman.io/en/latest/markdown/podman-run.1.html#privileged&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://docs.redhat.com/en/documentation/red_hat_enterprise_linux/9/html/building_running_and_managing_containers/assembly_running-special-container-images#con_opening-privileges-to-the-host_assembly_running-special-container-images&#34;&gt;https://docs.redhat.com/en/documentation/red_hat_enterprise_linux/9/html/building_running_and_managing_containers/assembly_running-special-container-images#con_opening-privileges-to-the-host_assembly_running-special-container-images&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Older examples for creating a registry use &lt;code&gt;--privileged&lt;/code&gt;.  I am just going to pull the explanation from the run documentation:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Give extended privileges to this container. The default is false.&lt;/p&gt;&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;By default, Podman containers are unprivileged (=false) and cannot, for example, modify parts of the operating system. This is because by default a container is only allowed limited access to devices. A “privileged” container is given the same access to devices as the user launching the container, with the exception of virtual consoles (/dev/tty\d+) when running in systemd mode (&amp;ndash;systemd=always).&lt;/p&gt;&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;A privileged container turns off the security features that isolate the container from the host. Dropped Capabilities, limited devices, read-only mount points, Apparmor/SELinux separation, and Seccomp filters are all disabled. Due to the disabled security features, the privileged field should almost never be set as containers can easily break out of confinement.&lt;/p&gt;&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;Containers running in a user namespace (e.g., rootless containers) cannot have more privileges than the user that launched them.&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;Newer examples leave this off, I suspect because narrower privileging around volumes seems to have improved in the intervening years. I am going to leave it off too, but wanted to mention it in case someone finds there way here after seeing an older example.&lt;/p&gt;
&lt;h3 id=&#34;how-will-podman-know-how-to-find-our-registry&#34;&gt;How will podman know how to find our registry?&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://docs.redhat.com/en/documentation/red_hat_enterprise_linux/9/html/building_running_and_managing_containers/working-with-container-registries_building-running-and-managing-containers#con_configuring-container-registries_working-with-container-registries&#34;&gt;https://docs.redhat.com/en/documentation/red_hat_enterprise_linux/9/html/building_running_and_managing_containers/working-with-container-registries_building-running-and-managing-containers#con_configuring-container-registries_working-with-container-registries&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://docs.redhat.com/en/documentation/red_hat_enterprise_linux/9/html/building_running_and_managing_containers/working-with-container-registries_building-running-and-managing-containers&#34;&gt;https://docs.redhat.com/en/documentation/red_hat_enterprise_linux/9/html/building_running_and_managing_containers/working-with-container-registries_building-running-and-managing-containers&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;To let podman know about the registry, update the &lt;code&gt;$HOME/.config/containers/registries.conf&lt;/code&gt; from the last post to add it to the unqualified-search-registries and to indicate that it isn&amp;rsquo;t secure.&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;unqualified-search-registries = [&amp;#34;localhost:5050&amp;#34;, &amp;#34;docker.io&amp;#34;, &amp;#34;ghrc.io&amp;#34;, &amp;#34;quay.io&amp;#34;, &amp;#34;registry.fedoraproject.org&amp;#34;]

[[registry]]
location=&amp;#34;localhost:5050&amp;#34;
insecure=true&amp;#39;
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&#34;summary&#34;&gt;Summary&lt;/h2&gt;
&lt;p&gt;So these are 5 options on how to get images out of the podman VM on the mac and out to somewhere that will survive if it&amp;rsquo;s nuked.&lt;/p&gt;
&lt;p&gt;The next post will be about improving our image, and maybe writing one from scratch.&lt;/p&gt;
</description>
    </item>
    
    
    
    <item>
      <title>Podman: How do I get and edit an image on MacOS?</title>
      <link>https://whynotestflight.com/excuses/podman-how-do-i-get-and-edit-an-image-on-macos/</link>
      <pubDate>Thu, 28 Aug 2025 00:00:00 +0000</pubDate>
      
      <guid>https://whynotestflight.com/excuses/podman-how-do-i-get-and-edit-an-image-on-macos/</guid>
      <description>&lt;p&gt;This may all be obsolete when using MacOS 26 because of the &lt;a href=&#34;https://github.com/apple/container&#34;&gt;containers&lt;/a&gt; announced at &lt;a href=&#34;https://developer.apple.com/videos/play/wwdc2025/346/&#34;&gt;WWDC25&lt;/a&gt;, but there is an open source version of docker called &lt;a href=&#34;https://podman.io&#34;&gt;podman&lt;/a&gt; that complies with the same &lt;a href=&#34;https://opencontainers.org&#34;&gt;Open Container Initiative&lt;/a&gt; &lt;a href=&#34;https://specs.opencontainers.org&#34;&gt;specs&lt;/a&gt; as the Apple containers.&lt;/p&gt;
&lt;p&gt;Why use podman now when I&amp;rsquo;ve avoided containers like the plague? I was looking to deploy a swift server and came across the &lt;a href=&#34;https://github.com/apple/swift-container-plugin&#34;&gt;swift container plugin&lt;/a&gt; thanks to the &lt;a href=&#34;https://hummingbird.codes&#34;&gt;Hummingbird&lt;/a&gt; folks, and was interested in seeing how it worked. What could it make easier about sharing swift server examples?&lt;/p&gt;
&lt;p&gt;The plugin &lt;em&gt;requires&lt;/em&gt; a registry, which I made on &lt;a href=&#34;https://digitalocean.com&#34;&gt;Digital Ocean&lt;/a&gt; (&lt;a href=&#34;https://m.do.co/c/2a910cd4cd9f&#34;&gt;affiliate link&lt;/a&gt;, why not), but I had troubles with it (the DO error code left something to be desired) and needed to explore containers in general to do a bit more to troubleshooting. Including figure out how to run a registry locally on my own computer.&lt;/p&gt;
&lt;p&gt;And because Docker irritated. me. so. much. the last time I used it, enter Podman.&lt;/p&gt;
&lt;p&gt;Podman &amp;ldquo;is an open source Open Container Initiative (OCI)-compliant container management tool from Red Hat used for handling containers, images, volumes, and pods&amp;rdquo; (&lt;a href=&#34;https://en.wikipedia.org/wiki/Podman&#34;&gt;https://en.wikipedia.org/wiki/Podman&lt;/a&gt;)&lt;/p&gt;
&lt;p&gt;Some tutorials are difficult to follow because they try to leverage a knowledge of Docker, and everything I learned about Docker a few years a go I&amp;rsquo;ve tried to actively forget. But these resources provided a nice base.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://www.redhat.com/en/topics/containers/what-is-podman&#34;&gt;https://www.redhat.com/en/topics/containers/what-is-podman&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://docs.podman.io/en/v5.2.4/Introduction.html&#34;&gt;https://docs.podman.io/en/v5.2.4/Introduction.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;QUICK &amp;amp; EASY START HERE -&amp;gt; &lt;a href=&#34;https://podman.io/get-started&#34;&gt;podman.io get started&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://www.youtube.com/watch?v=YXfA5O5Mr18&#34;&gt;Podman Tutorial Zero to Hero | Full 1 Hour Course&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;install-podman&#34;&gt;Install Podman&lt;/h2&gt;
&lt;p&gt;There are two options for installing podman on the mac. CLI only (first) and CLI with GUI (second).&lt;/p&gt;
&lt;p&gt;I don&amp;rsquo;t find the GUI that intuitive, so while I do have it installed, I haven&amp;rsquo;t been using it. The install process may have tweaked some settings around docker and it installed a couple extra tools. I will be keeping a look out for commands that might work differently because I installed it, but nothing I&amp;rsquo;ve done so far appears to have changed from before and after.&lt;/p&gt;
&lt;p&gt;(As a note, one can&amp;rsquo;t stop the podman server from running if the GUI is open.)&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-shell&#34; data-lang=&#34;shell&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## CLI Only&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;brew install podman
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## install GUI that will also install CLI&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;brew install --cask podman-desktop
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Note: to use docker.io later to retrieve the base project one option is to install it and login that way. I think you could leave it out and choose a different base project, but I was just following along. At least it made ME do that. YMMV.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-shell&#34; data-lang=&#34;shell&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;brew install docker
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## will lead you through the steps to create a login and that shell will be able&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## to access docker.io just fine at the least. &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;docker login 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## it doesn&amp;#39;t change .zprofile but it does create a config file. For more info:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# cat ~/.docker/config.json&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Afterwards I realized there was a &lt;a href=&#34;https://docs.podman.io/en/latest/markdown/podman-login.1.html&#34;&gt;podman login&lt;/a&gt; command, but I have yet to try it.&lt;/p&gt;
&lt;h2 id=&#34;set-up-and-launch-the-podman-vm&#34;&gt;Set up and launch the podman VM&lt;/h2&gt;
&lt;p&gt;Podman is a linux only tool, so on the Mac podman runs in a linux VM that will need to be created and then ssh&amp;rsquo;d into to configure.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-shell&#34; data-lang=&#34;shell&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;podman machine init
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;podman machine start
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://docs.podman.io/en/latest/markdown/podman-machine-init.1.html&#34;&gt;https://docs.podman.io/en/latest/markdown/podman-machine-init.1.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://docs.podman.io/en/latest/markdown/podman-machine-start.1.html&#34;&gt;https://docs.podman.io/en/latest/markdown/podman-machine-start.1.html&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If for any reason you want to nuke it and start again:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-shell&#34; data-lang=&#34;shell&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;podman machine stop
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;podman machine rm
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;podman machine init
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;podman machine start
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://docs.podman.io/en/latest/markdown/podman-machine-stop.1.html&#34;&gt;https://docs.podman.io/en/latest/markdown/podman-machine-stop.1.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://docs.podman.io/en/latest/markdown/podman-machine-rm.1.html&#34;&gt;https://docs.podman.io/en/latest/markdown/podman-machine-rm.1.html&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;You can find out more information about your set up by running &lt;a href=&#34;https://docs.podman.io/en/latest/markdown/podman-info.1.html&#34;&gt;info&lt;/a&gt; and &lt;a href=&#34;https://docs.podman.io/en/latest/markdown/podman-version.1.html&#34;&gt;version&lt;/a&gt;&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-shell&#34; data-lang=&#34;shell&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;podman info
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;podman version
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://docs.podman.io/en/latest/Commands.html&#34;&gt;List of podman commands&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://docs.podman.io/en/latest/markdown/podman-machine.1.html&#34;&gt;List of podman machine commands&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;tell-it-what-registries-you-prefer-it-to-search&#34;&gt;Tell it what registries you prefer it to search&lt;/h2&gt;
&lt;p&gt;Updating the &lt;code&gt;registries.conf&lt;/code&gt; file to control what registries podman will search isn&amp;rsquo;t in the getting started tutorial, but it is in the video.&lt;/p&gt;
&lt;p&gt;What the video skips, is that on the mac, in order to update the VM running the podman tool, you&amp;rsquo;ll need to ssh into it and &lt;em&gt;then&lt;/em&gt; follow tutorial instructions.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-shell&#34; data-lang=&#34;shell&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# https://docs.podman.io/en/latest/markdown/podman-machine-ssh.1.html&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;podman machine ssh
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Once in, add the registries to a config file in the VM user&amp;rsquo;s directory so you don&amp;rsquo;t have to change the main one for the whole VM, but on the VM it&amp;rsquo;s less of a big deal to change the main one than when running directly on a linux box, I would suspect.&lt;/p&gt;
&lt;p&gt;Look at the VM&amp;rsquo;s main file:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-shell&#34; data-lang=&#34;shell&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;cat /etc/containers/registries.conf
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Make a local user one if desired (this one matches the video tutorial):&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-shell&#34; data-lang=&#34;shell&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#91d7e3&#34;&gt;echo&lt;/span&gt; -e &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#39;unqualified-search-registries = [&amp;#34;docker.io&amp;#34;, &amp;#34;ghrc.io&amp;#34;, &amp;#34;quay.io&amp;#34;, &amp;#34;registry.fedoraproject.org&amp;#34;]&amp;#39;&lt;/span&gt; &amp;gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;$HOME&lt;/span&gt;/.config/containers/registries.conf
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;get-an-existing-container-image&#34;&gt;Get an Existing Container Image&lt;/h2&gt;
&lt;p&gt;The getting started tutorial picks a really simple http server which is perfect to kick off with.&lt;/p&gt;
&lt;p&gt;The tutorial of course starts with showing how to &lt;a href=&#34;https://docs.podman.io/en/v3.2.3/markdown/podman-search.1.html&#34;&gt;search&lt;/a&gt; for it.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-shell&#34; data-lang=&#34;shell&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# all the things with that name&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;podman search httpd
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# flagged official&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;podman search httpd --filter&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt;is-official
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;From the documentation, supported filters are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;stars (int - number of stars the image has)&lt;/li&gt;
&lt;li&gt;is-automated (boolean - true | false) - is the image automated or not&lt;/li&gt;
&lt;li&gt;is-official (boolean - true | false) - is the image official or not&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;a href=&#34;https://docs.podman.io/en/stable/markdown/podman-pull.1.html&#34;&gt;Pull&lt;/a&gt; the desired container image onto your machine and &lt;a href=&#34;https://docs.podman.io/en/stable/markdown/podman-run.1.html&#34;&gt;run&lt;/a&gt; it.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-shell&#34; data-lang=&#34;shell&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;podman pull docker.io/library/httpd:latest 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;podman run -dt -p 8080:80/tcp docker.io/library/httpd
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;Run&lt;/code&gt; is used for when the container doesn&amp;rsquo;t exist yet. Some folks add a &lt;a href=&#34;https://docs.podman.io/en/stable/markdown/podman-run.1.html#rm&#34;&gt;&lt;code&gt;--rm&lt;/code&gt;&lt;/a&gt; to the command so a container being created that one doesn&amp;rsquo;t intend to edit will get zotted when it&amp;rsquo;s wound down. &lt;a href=&#34;https://docs.podman.io/en/stable/markdown/podman-run.1.html#rmi&#34;&gt;&lt;code&gt;--rmi&lt;/code&gt;&lt;/a&gt; will delete the image!&lt;/p&gt;
&lt;p&gt;This example command uses &lt;a href=&#34;https://docs.podman.io/en/latest/markdown/podman-run.1.html#detach-d&#34;&gt;-d&lt;/a&gt; for detached. That will let the process run in the background.  The &lt;a href=&#34;https://docs.podman.io/en/latest/markdown/podman-run.1.html#tty-t&#34;&gt;-t&lt;/a&gt; also adds a pseudo-tty to run arbitrary commands in an interactive shell.&lt;/p&gt;
&lt;p&gt;The string of numbers you&amp;rsquo;ll see after executing is the full ID string of the container that has been made from the image.&lt;/p&gt;
&lt;p&gt;If you forget that string you can get it again by running &lt;a href=&#34;https://docs.podman.io/en/latest/markdown/podman-ps.1.html&#34;&gt;ps&lt;/a&gt; which shows the running containers. The shortened string works just as well as an id later.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-shell&#34; data-lang=&#34;shell&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# currently running&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;podman ps
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# even ones that have been stopped.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;podman ps -a
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;To end a specific process use &lt;a href=&#34;https://docs.podman.io/en/latest/markdown/podman-stop.1.html&#34;&gt;stop&lt;/a&gt; using that ID number. If you didn&amp;rsquo;t add -rm, it can be restarted with &lt;a href=&#34;https://docs.podman.io/en/latest/markdown/podman-start.1.html&#34;&gt;start&lt;/a&gt;.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-shell&#34; data-lang=&#34;shell&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;podman stop &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;{&lt;/span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;$CONTAINER_ID&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;podman start &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;{&lt;/span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;$CONTAINER_ID&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;With this image up and running you should be able to hit the demo web page:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-shell&#34; data-lang=&#34;shell&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;curl http://localhost:8080
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#&amp;lt;html&amp;gt;&amp;lt;body&amp;gt;&amp;lt;h1&amp;gt;Still works!&amp;lt;/h1&amp;gt;&amp;lt;/body&amp;gt;&amp;lt;/html&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;make-changes-to-it&#34;&gt;Make changes to it&amp;hellip;&lt;/h3&gt;
&lt;p&gt;Let&amp;rsquo;s say you wanted to change that web page. With the container still running, launch its bash with &lt;a href=&#34;https://docs.podman.io/en/latest/markdown/podman-exec.1.html&#34;&gt;&lt;code&gt;exec&lt;/code&gt;&lt;/a&gt; &lt;a href=&#34;https://docs.podman.io/en/latest/markdown/podman-exec.1.html#interactive-i&#34;&gt;&lt;code&gt;-i&lt;/code&gt;&lt;/a&gt; &lt;a href=&#34;https://docs.podman.io/en/latest/markdown/podman-exec.1.html#tty-t&#34;&gt;&lt;code&gt;-t&lt;/code&gt;&lt;/a&gt;, where -i is interactive and -t is that tty again. Don&amp;rsquo;t forget to add the tool you want to launch at the end!&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-shell&#34; data-lang=&#34;shell&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;podman &lt;span style=&#34;color:#91d7e3&#34;&gt;exec&lt;/span&gt; -it &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;{&lt;/span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;$CONTAINER_ID&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;}&lt;/span&gt; bash
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Once in the interactive shell one can change the web page.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-shell&#34; data-lang=&#34;shell&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ls -al
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#91d7e3&#34;&gt;echo&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#39;&amp;lt;html&amp;gt;&amp;lt;body&amp;gt;&amp;lt;h1&amp;gt;Still works!&amp;lt;/h1&amp;gt;&amp;lt;/body&amp;gt;&amp;lt;/html&amp;gt;&amp;#39;&lt;/span&gt; &amp;gt; htdocs/index.html
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;In a different Terminal, try the curl again. It should reflect the new page.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-shell&#34; data-lang=&#34;shell&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;curl http://localhost:8080
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# &amp;lt;html&amp;gt;&amp;lt;body&amp;gt;&amp;lt;h1&amp;gt;Still works!&amp;lt;/h1&amp;gt;&amp;lt;/body&amp;gt;&amp;lt;/html&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Stop, start and curl again&amp;hellip; The changes are preserved!&lt;/p&gt;
&lt;h2 id=&#34;make-a-new-image-from-an-existing-container&#34;&gt;Make a new image from an existing container&lt;/h2&gt;
&lt;p&gt;Let&amp;rsquo;s say you want to make a new image from this changed container. That&amp;rsquo;s what the &lt;a href=&#34;https://docs.podman.io/en/latest/markdown/podman-commit.1.html&#34;&gt;&lt;code&gt;commit&lt;/code&gt;&lt;/a&gt; command is for.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-shell&#34; data-lang=&#34;shell&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## see containers&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;podman ps -a
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## see images&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;podman images 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## will provide default info (best for shared environments)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# podman commit {$CONTAINER_ID} &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;podman commit &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;{&lt;/span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;$CONTAINER_ID&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;}&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;{&lt;/span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;$SOME_HUMAN_READABLE_LABEL_FOR_NEW&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## look for new image&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;podman images 
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;I chose &amp;ldquo;my-httpd-template&amp;rdquo; for my new &lt;code&gt;localhost/my-httpd-template&lt;/code&gt; now lives in my list of images, and I can make new containers from it instead of the one from the registry.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-shell&#34; data-lang=&#34;shell&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;podman run -dt -p 8080:80/tcp localhost/my-httpd-template
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## see it running&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;podman ps
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;until-next-post&#34;&gt;Until next post&lt;/h2&gt;
&lt;p&gt;This is a handy place to stop this section of notes because we now have a our own new copy of an image that we made changes to, and can make changes to.&lt;/p&gt;
&lt;p&gt;The next set of notes all covers how to share an image once you have it, i.e. various ways of copying it out of the VM, pushing it to a remote registry, pushing it to a local registry, etc.&lt;/p&gt;
</description>
    </item>
    
    
    
    <item>
      <title>DocC: notes on getting started</title>
      <link>https://whynotestflight.com/excuses/docc-notes-on-getting-started/</link>
      <pubDate>Sat, 05 Jul 2025 00:00:00 +0000</pubDate>
      
      <guid>https://whynotestflight.com/excuses/docc-notes-on-getting-started/</guid>
      <description>&lt;p&gt;&lt;a href=&#34;https://github.com/swiftlang/swift-docc&#34;&gt;DocC&lt;/a&gt; solves two different problems. It helps automate API documentation, and it also provides a system for writing support articles and tutorials.&lt;/p&gt;
&lt;p&gt;This article is mostly rough notes on the meta of how to view &lt;code&gt;DocC&lt;/code&gt; docs, how generate the output and handle the output outside of the XCode ecosystem.&lt;/p&gt;
&lt;h2 id=&#34;additional-resources&#34;&gt;Additional Resources&lt;/h2&gt;
&lt;p&gt;There are additional resources listed inline with the notes, but here are some not otherwise mentioned but helpful .&lt;/p&gt;
&lt;h3 id=&#34;wwdc&#34;&gt;WWDC&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;2021
&lt;ul&gt;
&lt;li&gt;year released as open source&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://developer.apple.com/news/?id=xa4ak3qr&#34;&gt;https://developer.apple.com/news/?id=xa4ak3qr&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Meet: &lt;a href=&#34;https://developer.apple.com/videos/play/wwdc2021/10166&#34;&gt;https://developer.apple.com/videos/play/wwdc2021/10166&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Host and Automate: &lt;a href=&#34;https://developer.apple.com/videos/play/wwdc2021/10236&#34;&gt;https://developer.apple.com/videos/play/wwdc2021/10236&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Elevate: &lt;a href=&#34;https://developer.apple.com/videos/play/wwdc2021/10167&#34;&gt;https://developer.apple.com/videos/play/wwdc2021/10167&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Build Tutorials: &lt;a href=&#34;https://developer.apple.com/videos/play/wwdc2021/10235&#34;&gt;https://developer.apple.com/videos/play/wwdc2021/10235&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;2022
&lt;ul&gt;
&lt;li&gt;What&amp;rsquo;s new in: &lt;a href=&#34;https://developer.apple.com/videos/play/wwdc2022/110368&#34;&gt;https://developer.apple.com/videos/play/wwdc2022/110368&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Improve discoverability: &lt;a href=&#34;https://developer.apple.com/videos/play/wwdc2022/110369&#34;&gt;https://developer.apple.com/videos/play/wwdc2022/110369&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;2023
&lt;ul&gt;
&lt;li&gt;Create rich: &lt;a href=&#34;https://developer.apple.com/videos/play/wwdc2023/10244&#34;&gt;https://developer.apple.com/videos/play/wwdc2023/10244&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;misc-others&#34;&gt;Misc Others&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://www.mongodb.com/developer/languages/swift/build-host-docc-documentation-using-github-actions-netlify/&#34;&gt;https://www.mongodb.com/developer/languages/swift/build-host-docc-documentation-using-github-actions-netlify/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://developer.apple.com/documentation/xcode/distributing-documentation-to-other-developers&#34;&gt;https://developer.apple.com/documentation/xcode/distributing-documentation-to-other-developers&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://forums.swift.org/t/support-hosting-docc-archives-in-static-hosting-environments/53572&#34;&gt;https://forums.swift.org/t/support-hosting-docc-archives-in-static-hosting-environments/53572&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://alexanderweiss.dev/blog/2025-03-09-docc-for-multi-platform-documentation&#34;&gt;https://alexanderweiss.dev/blog/2025-03-09-docc-for-multi-platform-documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://forums.swift.org/t/support-hosting-docc-archives-in-static-hosting-environments/53572&#34;&gt;https://forums.swift.org/t/support-hosting-docc-archives-in-static-hosting-environments/53572&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://forums.swift.org/t/docc-render-with-a-static-html-generator/73866&#34;&gt;https://forums.swift.org/t/docc-render-with-a-static-html-generator/73866&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/swiftlang/swift-docc/blob/main/Sources/SwiftDocC/SwiftDocC.docc/Resources/RenderNode.spec.json&#34;&gt;https://github.com/swiftlang/swift-docc/blob/main/Sources/SwiftDocC/SwiftDocC.docc/Resources/RenderNode.spec.json&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/tayloraswift/swift-unidoc&#34;&gt;https://github.com/tayloraswift/swift-unidoc&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;getting-help-via-the-command-line&#34;&gt;Getting Help via the Command line&lt;/h2&gt;
&lt;p&gt;These are the different commands I found:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;## stand alone
docc --help
## xcode project related
xcrun docc --help
xcodebuild docbuild -- help
## package
swift package plugin generate-documentation --help
&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=&#34;resources&#34;&gt;Resources&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://thisdevbrain.com/build-docc-documentation-using-command-line/&#34;&gt;https://thisdevbrain.com/build-docc-documentation-using-command-line/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://developer.apple.com/videos/play/wwdc2021/10236/&#34;&gt;https://developer.apple.com/videos/play/wwdc2021/10236/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://stackoverflow.com/questions/69787722/how-to-build-docc-documentation-from-cli&#34;&gt;https://stackoverflow.com/questions/69787722/how-to-build-docc-documentation-from-cli&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://swiftlang.github.io/swift-docc-plugin/documentation/swiftdoccplugin/&#34;&gt;https://swiftlang.github.io/swift-docc-plugin/documentation/swiftdoccplugin/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://www.swift.org/documentation/docc/distributing-documentation-to-other-developers&#34;&gt;https://www.swift.org/documentation/docc/distributing-documentation-to-other-developers&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;how-to-view-your-work&#34;&gt;How to View Your Work&lt;/h2&gt;
&lt;h3 id=&#34;xcode-open-the-documentation-preview&#34;&gt;XCode: Open the Documentation Preview&lt;/h3&gt;
&lt;p&gt;The fastest way to see the results of your DocC work is to use Xcode and open the documentation window (&lt;code&gt;Window &amp;gt; Developer Documentation (Shft-Cmd-0)&lt;/code&gt;).&lt;/p&gt;
&lt;p&gt;But the most convenient while working on it is to have the Documentation Preview open.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;You can access Documentation Preview by first activating the assistant editor via Editor &amp;gt; Assistant, and then selecting “Documentation Preview” in the assistant editor’s jump bar.&lt;/p&gt;&lt;/blockquote&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://developer.apple.com/documentation/xcode-release-notes/xcode-15-release-notes#Documentation&#34;&gt;https://developer.apple.com/documentation/xcode-release-notes/xcode-15-release-notes#Documentation&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;To actually build the docs &lt;code&gt;Product &amp;gt; Build Documentation&lt;/code&gt;&lt;/p&gt;
&lt;h3 id=&#34;vscode&#34;&gt;VSCode&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://www.swift.org/documentation/articles/getting-started-with-vscode-swift.html&#34;&gt;https://www.swift.org/documentation/articles/getting-started-with-vscode-swift.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://docs.swift.org/vscode/documentation/userdocs/docc-live-preview/&#34;&gt;https://docs.swift.org/vscode/documentation/userdocs/docc-live-preview/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Purportedly when using 6.2 or higher there&amp;rsquo;s a docc preview available. I haven&amp;rsquo;t fully checked that out. I could not get it to work when using a swiftly &lt;code&gt;.swift-version&lt;/code&gt; file to drive using 6.2&lt;/p&gt;
&lt;p&gt;i.e.:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;swiftly use 6.2-snapshot-2025-06-12
swiftly run swift package plugin generate-documentation 
&lt;/code&gt;&lt;/pre&gt;&lt;blockquote&gt;
&lt;p&gt;View a side-by-side live preview of your documentation as you edit it with the Swift extension for VS Code. Access this feature using the Preview Swift Documentation button at the top right of an editor, or be invoking &lt;code&gt;Swift: Preview Documentation&lt;/code&gt; in the command palette. This opens up a new editor pane with your rendered documentation:&lt;/p&gt;&lt;/blockquote&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://docs.swift.org/vscode/documentation/userdocs/docc-live-preview/&#34;&gt;https://docs.swift.org/vscode/documentation/userdocs/docc-live-preview/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;TODO: check it out with the system&amp;rsquo;s default toolchain set to 6.2&lt;/p&gt;
&lt;h3 id=&#34;package-commandline-and-a-browser&#34;&gt;Package: commandline and a browser.&lt;/h3&gt;
&lt;h4 id=&#34;using-the-package-plugin-directly&#34;&gt;Using the Package Plugin Directly&lt;/h4&gt;
&lt;p&gt;Add it to your Package dependencies:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    ],
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        dependencies: [
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        .package(url: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;https://github.com/apple/swift-docc-plugin&amp;#34;&lt;/span&gt;, from: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;1.0.0&amp;#34;&lt;/span&gt;),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    ],
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;generate and launch preview:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;swift package plugin generate-documentation
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;swift package --disable-sandbox preview-documentation --target &lt;span style=&#34;color:#f4dbd6&#34;&gt;$TARGET_NAME&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## or&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;swift package --disable-sandbox preview-documentation --product &lt;span style=&#34;color:#f4dbd6&#34;&gt;$PRODUCT_NAME&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://swiftlang.github.io/swift-docc-plugin/documentation/swiftdoccplugin/&#34;&gt;https://swiftlang.github.io/swift-docc-plugin/documentation/swiftdoccplugin/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;command-line&#34;&gt;Command Line&lt;/h3&gt;
&lt;p&gt;The &lt;code&gt;docc&lt;/code&gt; command for generating an archive is &lt;code&gt;convert&lt;/code&gt;. Highly recommend checking out the  help to see what&amp;rsquo;s possible:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;which docc
docc convert -- help
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The example convert provided is:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-zsh&#34; data-lang=&#34;zsh&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;docc convert MyNewPackage.docc &lt;span style=&#34;color:#8aadf4&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;&lt;/span&gt;  --fallback-display-name MyNewPackage &lt;span style=&#34;color:#8aadf4&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;&lt;/span&gt;  --fallback-bundle-identifier com.example.MyNewPackage &lt;span style=&#34;color:#8aadf4&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;&lt;/span&gt;  --fallback-bundle-version &lt;span style=&#34;color:#f5a97f&#34;&gt;1&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;&lt;/span&gt;  --additional-symbol-graph-dir .build &lt;span style=&#34;color:#8aadf4&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;&lt;/span&gt;  --output-dir MyNewPackage.doccarchive
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;So from the package root of my example project:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-zsh&#34; data-lang=&#34;zsh&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;DocCExplorer % docc convert Sources/DocCExplorer/DocCExplorer.docc &lt;span style=&#34;color:#8aadf4&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;&lt;/span&gt;--fallback-display-name DocCExplorer &lt;span style=&#34;color:#8aadf4&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;&lt;/span&gt;--additional-symbol-graph-dir .build &lt;span style=&#34;color:#8aadf4&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;&lt;/span&gt;--output-dir ~/Desktop/DocCExplorer.doccarchive
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;working-with-an-archive&#34;&gt;Working with an archive&lt;/h2&gt;
&lt;h3 id=&#34;finding-an-archive-built-fo-a-package&#34;&gt;Finding an archive built fo a package&lt;/h3&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-zsh&#34; data-lang=&#34;zsh&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## from the package root folder&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## will return both preview builds and output builds&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;find . -type d -name &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;*.doccarchive&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## poke around inside&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#91d7e3&#34;&gt;cd&lt;/span&gt; .build/plugins/Swift-DocC&lt;span style=&#34;color:#8aadf4&#34;&gt;\ &lt;/span&gt;Preview/outputs/&lt;span style=&#34;color:#f4dbd6&#34;&gt;$TARGET_NAME&lt;/span&gt;.doccarchive
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## OR move it&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;cp -r .build/plugins/Swift-DocC/outputs/&lt;span style=&#34;color:#f4dbd6&#34;&gt;$TARGET_NAME&lt;/span&gt;.doccarchive &lt;span style=&#34;color:#f4dbd6&#34;&gt;$NEW_LOCATION&lt;/span&gt;/&lt;span style=&#34;color:#f4dbd6&#34;&gt;$TARGET_NAME&lt;/span&gt;.doccarchive
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;what-is-in-an-archive&#34;&gt;What is in an archive&lt;/h3&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;css				
data				
developer-og-twitter.jpg	
developer-og.jpg		
documentation			
downloads			
favicon.ico			
favicon.svg
images
img
index
index.html
js
metadata.json
videos
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;cd&amp;rsquo;ing into that dir and running &lt;code&gt;python3 -m http.server $PORT&lt;/code&gt;, works, but one will have to navigate by hand down into a subfolder. (that subfolder can be reset see below)&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-zsh&#34; data-lang=&#34;zsh&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;http://localhost:&lt;span style=&#34;color:#f4dbd6&#34;&gt;$PORT&lt;/span&gt;/documentation/&lt;span style=&#34;color:#f4dbd6&#34;&gt;$TARGET_NAME&lt;/span&gt;/
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;What&amp;rsquo;s interesting is the &lt;code&gt;data&lt;/code&gt; folder which will contain json files for all the inline documentation.&lt;/p&gt;
&lt;p&gt;The files come out pretty bulky, and seem to use &lt;code&gt;Vue.js&lt;/code&gt; to run as an app and &lt;code&gt;webpack&lt;/code&gt; to minfy.&lt;/p&gt;
&lt;p&gt;One recommended script to &amp;ldquo;get it ready for static hosting&amp;rdquo;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-zsh&#34; data-lang=&#34;zsh&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;docc process-archive &lt;span style=&#34;color:#8aadf4&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;&lt;/span&gt;transform-for-static-hosting &lt;span style=&#34;color:#f4dbd6&#34;&gt;$PATH_TO_DOCCARCHIVE_FILE&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;&lt;/span&gt;--output-path &lt;span style=&#34;color:#f4dbd6&#34;&gt;$PATH_TO_SAVE_FILES&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;&lt;/span&gt;--hosting-base-path &lt;span style=&#34;color:#f4dbd6&#34;&gt;$URL_BASE_PATH&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;So from the same directory as an example doccarchive file, the below command changed it in place and didn&amp;rsquo;t change the root directory and got 34 changed files from running:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-zsh&#34; data-lang=&#34;zsh&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## in the folder with the doccarchive&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;docc process-archive &lt;span style=&#34;color:#8aadf4&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;&lt;/span&gt;transform-for-static-hosting ./DocCExplorer.doccarchive &lt;span style=&#34;color:#8aadf4&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;In the HTML files, which essentially are just light frames for javascript, new js files get swapped in. Because the js files come out all minimized it was irritating to figure out what was different exactly, so I didn&amp;rsquo;t.&lt;/p&gt;
&lt;p&gt;The actual function run is the &lt;a href=&#34;https://github.com/swiftlang/swift-docc/blob/c7660bb4f428db5f7651b26a02beb58fe701d662/Sources/SwiftDocCUtilities/Action/Actions/TransformForStaticHostingAction.swift#L15&#34;&gt;TransformForStaticHosting&lt;/a&gt; command.&lt;/p&gt;
&lt;p&gt;Looking at that code it looks like it&amp;rsquo;s more or less a straight copy when using a &lt;code&gt;--output-path&lt;/code&gt; if not also changing the &lt;code&gt;hosting-base-path&lt;/code&gt;.&lt;/p&gt;
</description>
    </item>
    
    
    
    <item>
      <title>Astro: how to write an integration as a package</title>
      <link>https://whynotestflight.com/excuses/astro-how-to-write-an-integration-as-a-package/</link>
      <pubDate>Mon, 30 Jun 2025 00:00:00 +0000</pubDate>
      
      <guid>https://whynotestflight.com/excuses/astro-how-to-write-an-integration-as-a-package/</guid>
      <description>&lt;p&gt;So I decided to look into &lt;a href=&#34;http://astro.build/&#34;&gt;Astro&lt;/a&gt; (yet another static site generator). Lots of reasons that I won&amp;rsquo;t get into for the sake of time, but two major ones:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;it&amp;rsquo;s a Typescript/Node set up&lt;/li&gt;
&lt;li&gt;seems pretty extendable because of that.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The official &lt;a href=&#34;https://docs.astro.build/en/tutorial/0-introduction/&#34;&gt;introductory tutorial&lt;/a&gt; does a fantastic job walking one through using it, although it is probably easier for people who already have some familiarly with HTML/css/Javascript/Node.&lt;/p&gt;
&lt;p&gt;Since I&amp;rsquo;m thinking about this for sites other than mine, I wanted to understand how to write features that could be used across more than one website, generally referred to as &amp;ldquo;&lt;code&gt;Integrations&lt;/code&gt;&amp;rdquo; in the Astro-verse.&lt;/p&gt;
&lt;p&gt;I found that name mildly confusing because many of the packages listed on &lt;a href=&#34;https://astro.build/integrations/&#34;&gt;Astro&amp;rsquo;s Integration&lt;/a&gt; page don&amp;rsquo;t actually take advantage of the &lt;a href=&#34;https://docs.astro.build/en/reference/integrations-reference/&#34;&gt;Integration API&lt;/a&gt; which gives a package &lt;code&gt;hooks&lt;/code&gt; into various stages of the build process, but merely take advantage of using Astro as a &lt;a href=&#34;https://docs.npmjs.com/cli/v11/configuring-npm/package-json#peerdependencies&#34;&gt;peerDependency&lt;/a&gt;. There doesn&amp;rsquo;t appear to be a separate names for node packages with those two different levels of enmeshment.&lt;/p&gt;
&lt;p&gt;Ultimately the best resources for me were:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/understanding-astro/understanding-astro-book/blob/master/ch8.md&#34;&gt;https://github.com/understanding-astro/understanding-astro-book/blob/master/ch8.md&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/florian-lefebvre/astro-integration-template&#34;&gt;https://github.com/florian-lefebvre/astro-integration-template&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;They can be found at the VEEEEERRRRRRYYYY bottom of the API page linked above, but they were also mentioned by the very helpful folks on the Astro discord.&lt;/p&gt;
&lt;p&gt;The first link had an example of an &lt;code&gt;integration&lt;/code&gt; implementation that was very easy to follow along with. The second link is a utility written by one of the maintainers of &lt;code&gt;Astro&lt;/code&gt; that generates a monorepo with an install of &lt;code&gt;Astro&lt;/code&gt; in it to help with testing. It&amp;rsquo;s a fantastic resource to get rolling on developing an &lt;code&gt;integration&lt;/code&gt; if you already know what you&amp;rsquo;re doing.&lt;/p&gt;
&lt;p&gt;I kinda needed something in the middle: an example of a simple integration in an stand alone package, but not a package full of bundlers and extra noise. I did not find one, so I made one.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/carlynorama/astro-integration-hello&#34;&gt;https://github.com/carlynorama/astro-integration-hello&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;It reproduces the in-package example in the first link as a very simple separate package.&lt;/p&gt;
&lt;p&gt;Below is a copy of the STEPS_TO_CREATE.md from that repo.&lt;/p&gt;
&lt;p&gt;The next step for this investigation will probably be to try to recreate the YouTube shortcode I did for this website as an &lt;code&gt;Astro&lt;/code&gt; &lt;code&gt;integration&lt;/code&gt;. There are &lt;a href=&#34;https://astro.build/integrations/?search=YouTube&#34;&gt;plenty of those already&lt;/a&gt; to crib from so seems like it should be a really reasonable exercise.&lt;/p&gt;
&lt;h2 id=&#34;repo-setup-information&#34;&gt;Repo Setup Information&lt;/h2&gt;
&lt;h3 id=&#34;commands-to-start-up&#34;&gt;Commands to Start Up&lt;/h3&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;npm init -y
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;npm install typescript @types/node --save-dev
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;npx tsc --init
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;npm install astro-integration-kit
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;npm install astro -D
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;touch README.md
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;touch LICENSE
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;touch .gitignore
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## UPDATE GITIGNORE FIRST!!!&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;git init; git add .; git commit -m &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Initialize repository&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;mkdir src
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;touch src/index.ts
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;touch integration/index.ts
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;mkdir scripts
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;touch src/scripts/support_script.ts
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;npm install kleur &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#this is to make the example code work exactly like the original demo. &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;gitignore&#34;&gt;.gitignore&lt;/h3&gt;
&lt;p&gt;copied from:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/florian-lefebvre/astro-integration-template/tree/main/templates/manual-kit&#34;&gt;https://github.com/florian-lefebvre/astro-integration-template/tree/main/templates/manual-kit&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# build output&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;dist/
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# generated types&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;.astro/
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# dependencies&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;node_modules/
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# logs&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;npm-debug.log*
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;yarn-debug.log*
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;yarn-error.log*
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;pnpm-debug.log*
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# environment variables&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;.env
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;.env.production
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# macOS-specific files&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;.DS_Store
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;tsconfigjson&#34;&gt;tsconfig.json&lt;/h3&gt;
&lt;p&gt;starting from the generated tsconfig, matched it to strictest by hand, but had to change some of the setting to better match what was reflected in the tsup settings of the example.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/withastro/astro/blob/main/packages/astro/tsconfigs/base.json&#34;&gt;https://github.com/withastro/astro/blob/main/packages/astro/tsconfigs/base.json&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/withastro/astro/blob/main/packages/astro/tsconfigs/strict.json&#34;&gt;https://github.com/withastro/astro/blob/main/packages/astro/tsconfigs/strict.json&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/withastro/astro/blob/main/packages/astro/tsconfigs/strictest.json&#34;&gt;https://github.com/withastro/astro/blob/main/packages/astro/tsconfigs/strictest.json&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/florian-lefebvre/astro-integration-template/blob/5944471673762c71672666b13217d89b7020583e/templates/manual-kit/package/tsup.config.ts#L4&#34;&gt;https://github.com/florian-lefebvre/astro-integration-template/blob/5944471673762c71672666b13217d89b7020583e/templates/manual-kit/package/tsup.config.ts#L4&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-json&#34; data-lang=&#34;json&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#c6a0f6&#34;&gt;&amp;#34;compilerOptions&amp;#34;&lt;/span&gt;: {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;/*&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;Visit&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;https:&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//aka.ms/tsconfig to read more about this file */
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;/*&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;Projects&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;*/&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;/*&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;Language&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;and&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;Environment&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;*/&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;&amp;#34;target&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;ESNext&amp;#34;&lt;/span&gt;,                                  &lt;span style=&#34;color:#ed8796&#34;&gt;/*&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;Set&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;the&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;JavaScript&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;language&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;version&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;for&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;emitted&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;JavaScript&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;and&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;include&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;compatible&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;library&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;declarations.&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;*/&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;&amp;#34;jsx&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;preserve&amp;#34;&lt;/span&gt;,                                   &lt;span style=&#34;color:#ed8796&#34;&gt;/*&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;Honestly&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;N/A&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;for&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;this&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;lib,&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;Specify&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;what&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;JSX&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;code&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;is&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;generated.&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;*/&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;/*&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;Modules&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;*/&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;&amp;#34;module&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;esnext&amp;#34;&lt;/span&gt;,                                  &lt;span style=&#34;color:#ed8796&#34;&gt;/*&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;Specify&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;what&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;module&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;code&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;is&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;generated.&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;*/&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//&amp;#34;rootDir&amp;#34;: &amp;#34;./src&amp;#34;,                                /* Specify the root folder within your source files. */
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;&amp;#34;moduleResolution&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;bundler&amp;#34;&lt;/span&gt;,                       &lt;span style=&#34;color:#ed8796&#34;&gt;/*&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;Specify&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;how&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;TypeScript&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;looks&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;up&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;a&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;file&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;from&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;a&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;given&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;module&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;specifier.&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;*/&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;&amp;#34;allowImportingTsExtensions&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#f5a97f&#34;&gt;false&lt;/span&gt;,                 &lt;span style=&#34;color:#ed8796&#34;&gt;/*&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;DIFFERENT&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;FROM&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;BASE&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;Allow&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;imports&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;to&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;include&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;TypeScript&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;file&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;extensions.&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;Requires&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;&amp;#39;--moduleResolution&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;bundler&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;and&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;either&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;&amp;#39;--noEmit&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;or&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;&amp;#39;--emitDeclarationOnly&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;to&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;be&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;set.&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;*/&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;/*&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;JavaScript&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;Support&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;*/&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;&amp;#34;allowJs&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#f5a97f&#34;&gt;true&lt;/span&gt;,                                     &lt;span style=&#34;color:#ed8796&#34;&gt;/*&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;Allow&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;JavaScript&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;files&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;to&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;be&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;a&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;part&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;of&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;your&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;program.&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;Use&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;the&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;&amp;#39;checkJS&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;option&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;to&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;get&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;errors&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;from&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;these&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;files.&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;*/&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;/*&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;Emit&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;*/&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;&amp;#34;declaration&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#f5a97f&#34;&gt;true&lt;/span&gt;,                                 &lt;span style=&#34;color:#ed8796&#34;&gt;/*&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;Generate&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;.d.ts&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;files&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;from&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;TypeScript&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;and&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;JavaScript&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;files&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;in&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;your&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;project.&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;*/&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;&amp;#34;sourceMap&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#f5a97f&#34;&gt;true&lt;/span&gt;,                                   &lt;span style=&#34;color:#ed8796&#34;&gt;/*&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;Create&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;source&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;map&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;files&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;for&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;emitted&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;JavaScript&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;files.&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;*/&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;&amp;#34;noEmit&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#f5a97f&#34;&gt;false&lt;/span&gt;,                                     &lt;span style=&#34;color:#ed8796&#34;&gt;/*&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;DIFFERENT&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;FROM&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;BASEDisable&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;emitting&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;files&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;from&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;a&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;compilation.&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;*/&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;&amp;#34;outDir&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;./dist&amp;#34;&lt;/span&gt;,                                  &lt;span style=&#34;color:#ed8796&#34;&gt;/*&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;Specify&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;an&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;output&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;folder&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;for&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;all&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;emitted&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;files.&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;*/&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;/*&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;Interop&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;Constraints&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;*/&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;&amp;#34;isolatedModules&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#f5a97f&#34;&gt;true&lt;/span&gt;,                             &lt;span style=&#34;color:#ed8796&#34;&gt;/*&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;Ensure&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;that&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;each&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;file&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;can&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;be&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;safely&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;transpiled&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;without&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;relying&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;on&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;other&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;imports.&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;*/&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;&amp;#34;verbatimModuleSyntax&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#f5a97f&#34;&gt;true&lt;/span&gt;,                        &lt;span style=&#34;color:#ed8796&#34;&gt;/*&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;Do&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;not&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;transform&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;or&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;elide&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;any&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;imports&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;or&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;exports&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;not&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;marked&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;as&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;type-only,&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;ensuring&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;they&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;are&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;written&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;in&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;the&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;output&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;file&amp;#39;s&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;format&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;based&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;on&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;the&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;&amp;#39;module&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;setting.&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;*/&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;&amp;#34;esModuleInterop&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#f5a97f&#34;&gt;true&lt;/span&gt;,                             &lt;span style=&#34;color:#ed8796&#34;&gt;/*&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;Emit&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;additional&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;JavaScript&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;to&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;ease&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;support&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;for&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;importing&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;CommonJS&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;modules.&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;This&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;enables&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;&amp;#39;allowSyntheticDefaultImports&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;for&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;type&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;compatibility.&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;*/&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;&amp;#34;forceConsistentCasingInFileNames&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#f5a97f&#34;&gt;true&lt;/span&gt;,            &lt;span style=&#34;color:#ed8796&#34;&gt;/*&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;Ensure&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;that&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;casing&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;is&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;correct&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;in&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;imports.&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;*/&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;/*&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;Type&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;Checking&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;*/&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;&amp;#34;strict&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#f5a97f&#34;&gt;true&lt;/span&gt;,                                      &lt;span style=&#34;color:#ed8796&#34;&gt;/*&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;Enable&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;all&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;strict&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;type-checking&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;options.&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;*/&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;&amp;#34;noUnusedLocals&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#f5a97f&#34;&gt;true&lt;/span&gt;,                              &lt;span style=&#34;color:#ed8796&#34;&gt;/*&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;Enable&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;error&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;reporting&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;when&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;local&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;variables&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;aren&amp;#39;t&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;read.&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;*/&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;&amp;#34;noUnusedParameters&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#f5a97f&#34;&gt;true&lt;/span&gt;,                          &lt;span style=&#34;color:#ed8796&#34;&gt;/*&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;Raise&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;an&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;error&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;when&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;a&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;function&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;parameter&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;isn&amp;#39;t&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;read.&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;*/&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;&amp;#34;exactOptionalPropertyTypes&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#f5a97f&#34;&gt;true&lt;/span&gt;,                  &lt;span style=&#34;color:#ed8796&#34;&gt;/*&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;Interpret&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;optional&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;property&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;types&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;as&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;written,&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;rather&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;than&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;adding&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;&amp;#39;undefined&amp;#39;.&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;*/&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;&amp;#34;noImplicitReturns&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#f5a97f&#34;&gt;true&lt;/span&gt;,                           &lt;span style=&#34;color:#ed8796&#34;&gt;/*&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;Enable&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;error&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;reporting&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;for&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;codepaths&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;that&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;do&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;not&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;explicitly&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;in&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;a&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;function.&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;*/&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;&amp;#34;noFallthroughCasesInSwitch&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#f5a97f&#34;&gt;true&lt;/span&gt;,                  &lt;span style=&#34;color:#ed8796&#34;&gt;/*&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;Enable&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;error&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;reporting&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;for&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;fallthrough&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;cases&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;in&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;switch&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;statements.&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;*/&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;&amp;#34;noUncheckedIndexedAccess&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#f5a97f&#34;&gt;true&lt;/span&gt;,                    &lt;span style=&#34;color:#ed8796&#34;&gt;/*&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;Add&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;&amp;#39;undefined&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;to&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;a&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;type&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;when&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;accessed&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;using&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;an&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;index.&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;*/&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;&amp;#34;noImplicitOverride&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#f5a97f&#34;&gt;true&lt;/span&gt;,                          &lt;span style=&#34;color:#ed8796&#34;&gt;/*&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;Ensure&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;overriding&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;members&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;in&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;derived&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;classes&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;are&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;marked&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;with&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;an&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;override&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;modifier.&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;*/&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;&amp;#34;allowUnusedLabels&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#f5a97f&#34;&gt;false&lt;/span&gt;,                          &lt;span style=&#34;color:#ed8796&#34;&gt;/*&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;Disable&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;error&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;reporting&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;for&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;unused&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;labels.&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;*/&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;&amp;#34;allowUnreachableCode&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#f5a97f&#34;&gt;false&lt;/span&gt;,                       &lt;span style=&#34;color:#ed8796&#34;&gt;/*&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;Disable&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;error&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;reporting&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;for&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;unreachable&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;code.&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;*/&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;/*&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;Completeness&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;*/&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;&amp;#34;skipLibCheck&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#f5a97f&#34;&gt;true&lt;/span&gt;                                 &lt;span style=&#34;color:#ed8796&#34;&gt;/*&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;Skip&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;type&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;checking&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;all&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;.d.ts&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;files.&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;*/&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  },
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#c6a0f6&#34;&gt;&amp;#34;include&amp;#34;&lt;/span&gt;: [
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;src/&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  ],
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#c6a0f6&#34;&gt;&amp;#34;exclude&amp;#34;&lt;/span&gt;: [
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;dist/&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  ]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;packagejson&#34;&gt;package.json&lt;/h3&gt;
&lt;p&gt;Some of the needed changes were made by the install scripts, but we&amp;rsquo;ll need a few more. Also there would be a lot more needed in order to publish correctly.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-json&#34; data-lang=&#34;json&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#c6a0f6&#34;&gt;&amp;#34;name&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;astro-integration-hello&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#c6a0f6&#34;&gt;&amp;#34;version&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;0.0.0&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#c6a0f6&#34;&gt;&amp;#34;description&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#c6a0f6&#34;&gt;&amp;#34;keywords&amp;#34;&lt;/span&gt;: [],
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#c6a0f6&#34;&gt;&amp;#34;author&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#c6a0f6&#34;&gt;&amp;#34;license&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Apache-2.0&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#c6a0f6&#34;&gt;&amp;#34;type&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;module&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#c6a0f6&#34;&gt;&amp;#34;exports&amp;#34;&lt;/span&gt;: {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;&amp;#34;.&amp;#34;&lt;/span&gt;: {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#c6a0f6&#34;&gt;&amp;#34;types&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;./dist/index.d.ts&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#c6a0f6&#34;&gt;&amp;#34;default&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;./dist/index.js&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    },
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;&amp;#34;./globalLog&amp;#34;&lt;/span&gt;: {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#c6a0f6&#34;&gt;&amp;#34;types&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;./dist/scripts/support_script.d.js&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#c6a0f6&#34;&gt;&amp;#34;default&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;./dist/scripts/support_script.js&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  },
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#c6a0f6&#34;&gt;&amp;#34;files&amp;#34;&lt;/span&gt;: [
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;dist&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  ],
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#c6a0f6&#34;&gt;&amp;#34;scripts&amp;#34;&lt;/span&gt;: {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;&amp;#34;build&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;tsc -b --verbose&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;&amp;#34;clean&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;rm -rf ./dist&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  },
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#c6a0f6&#34;&gt;&amp;#34;peerDependencies&amp;#34;&lt;/span&gt;: {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;&amp;#34;astro&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;^5.0.0&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  },
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#c6a0f6&#34;&gt;&amp;#34;dependencies&amp;#34;&lt;/span&gt;: {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;&amp;#34;astro-integration-kit&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;^0.18.0&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;&amp;#34;kleur&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;^4.1.5&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  },
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#c6a0f6&#34;&gt;&amp;#34;devDependencies&amp;#34;&lt;/span&gt;: {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;&amp;#34;@types/node&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;^24.0.4&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;&amp;#34;astro&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;^5.10.1&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;&amp;#34;typescript&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;^5.8.3&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h4 id=&#34;type&#34;&gt;type&lt;/h4&gt;
&lt;p&gt;&amp;ldquo;type&amp;rdquo;: &amp;ldquo;commonjs&amp;rdquo;, =&amp;gt; &amp;ldquo;type&amp;rdquo;: &amp;ldquo;module&amp;rdquo;,&lt;/p&gt;
&lt;h4 id=&#34;main---exportsfiles&#34;&gt;main -&amp;gt; exports/files&lt;/h4&gt;
&lt;p&gt;Uses the more modern exports syntax.  Also set up an entry point for the reference to the logging script.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://nodejs.org/api/packages.html#exports&#34;&gt;https://nodejs.org/api/packages.html#exports&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-json&#34; data-lang=&#34;json&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;exports&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;:&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;&amp;#34;.&amp;#34;&lt;/span&gt;: {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#c6a0f6&#34;&gt;&amp;#34;types&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;./dist/index.d.ts&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#c6a0f6&#34;&gt;&amp;#34;default&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;./dist/index.js&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    },
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;&amp;#34;./globalLog&amp;#34;&lt;/span&gt;: {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#c6a0f6&#34;&gt;&amp;#34;types&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;./dist/scripts/support_script.d.js&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#c6a0f6&#34;&gt;&amp;#34;default&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;./dist/scripts/support_script.js&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }&lt;span style=&#34;color:#ed8796&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;files&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;:&lt;/span&gt; [
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;dist&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  ]&lt;span style=&#34;color:#ed8796&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h4 id=&#34;scripts&#34;&gt;scripts&lt;/h4&gt;
&lt;p&gt;Add them.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-json&#34; data-lang=&#34;json&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;scripts&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;:&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;&amp;#34;build&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;tsc -b --verbose&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;&amp;#34;clean&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;rm -rf ./dist&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }&lt;span style=&#34;color:#ed8796&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h4 id=&#34;peerdependency&#34;&gt;peerDependency&lt;/h4&gt;
&lt;p&gt;Since this isn&amp;rsquo;t a mono repo where the plugin could be easily checked inside a running Astro instance. went ahead and installed astro as a dev dependency. Still need to add it as peerDependency by hand for other environments.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-json&#34; data-lang=&#34;json&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;peerDependencies&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;:&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;&amp;#34;astro&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;^5.10.1&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }&lt;span style=&#34;color:#ed8796&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;indexts&#34;&gt;index.ts&lt;/h3&gt;
&lt;p&gt;exports the integration as the default export.&lt;/p&gt;
&lt;p&gt;Note the &lt;em&gt;js&lt;/em&gt; in the import statement. To import &lt;code&gt;./integration.ts&lt;/code&gt;, &lt;code&gt;&#39;allowImportingTsExtensions&#39;&lt;/code&gt; would need to be enabled in the tsconfig. That option requires noEmit to also be enabled, and we need to emit.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/florian-lefebvre/astro-integration-template/blob/5944471673762c71672666b13217d89b7020583e/templates/manual-kit/package/src/index.ts&#34;&gt;https://github.com/florian-lefebvre/astro-integration-template/blob/5944471673762c71672666b13217d89b7020583e/templates/manual-kit/package/src/index.ts&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This uses the word &lt;code&gt;integration&lt;/code&gt; in the file name and object name but that isn&amp;rsquo;t required.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-typescript&#34; data-lang=&#34;typescript&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;import&lt;/span&gt; { integration } &lt;span style=&#34;color:#c6a0f6&#34;&gt;from&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;./integration.js&amp;#34;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;export&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;default&lt;/span&gt; integration;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;integrationts&#34;&gt;integration.ts&lt;/h3&gt;
&lt;p&gt;This is the file that emits the js file referred to in the &lt;code&gt;index.ts&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;It contains an almost exact dupe of &lt;code&gt;src/integrations/astro-hello.ts&lt;/code&gt; from &lt;a href=&#34;https://github.com/understanding-astro/understanding-astro-book/blob/master/ch8.md&#34;&gt;Understanding Astro: Integrations&lt;/a&gt;, except we import the &lt;a href=&#34;https://nodejs.org/api/packages.html#package-entry-points&#34;&gt;entry point&lt;/a&gt; that was set up in the &lt;code&gt;package.json&lt;/code&gt; instead of a local file reference.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-javascript&#34; data-lang=&#34;javascript&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;import&lt;/span&gt; { defineIntegration } from &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;astro-integration-kit&amp;#34;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;import&lt;/span&gt; kleur from &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;kleur&amp;#34;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;const&lt;/span&gt; dateTimeFormat &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;new&lt;/span&gt; Intl.DateTimeFormat([], {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  hour&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;2-digit&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  minute&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;2-digit&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  second&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;2-digit&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;});
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;const&lt;/span&gt; logServerMessage &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; (message&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;) =&amp;gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#c6a0f6&#34;&gt;const&lt;/span&gt; date &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; dateTimeFormat.format(&lt;span style=&#34;color:#c6a0f6&#34;&gt;new&lt;/span&gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;Date&lt;/span&gt;());
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  console.log(&lt;span style=&#34;color:#a6da95&#34;&gt;`&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;${&lt;/span&gt;kleur.gray(date)&lt;span style=&#34;color:#a6da95&#34;&gt;}&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;${&lt;/span&gt;kleur
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    .bold()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    .cyan(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;[astro-hello-integration]&amp;#34;&lt;/span&gt;)&lt;span style=&#34;color:#a6da95&#34;&gt;}&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;${&lt;/span&gt;message&lt;span style=&#34;color:#a6da95&#34;&gt;}&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;    `&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;};
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;export&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;const&lt;/span&gt; integration &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; defineIntegration({
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	name&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;astro-integration-hello&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	setup() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;		&lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;			hooks&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;:&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;				&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;astro:config:setup&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;:&lt;/span&gt; (options) =&amp;gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;					options.injectScript(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;						&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;page&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//THIS IS WHAT&amp;#39;S DIFFERENT!!! 
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;						&lt;span style=&#34;color:#a6da95&#34;&gt;`import &amp;#34;astro-integration-hello/globalLog&amp;#34;;`&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;					)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;					logServerMessage(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Integration Happened&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;				}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;				
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;			},
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;		};
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	},
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;});
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Aside: one does a full &lt;code&gt;import&lt;/code&gt; instead of just passing in a file name because that second parameter is a raw code string.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-javascript&#34; data-lang=&#34;javascript&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;export&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;const&lt;/span&gt; integration &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; defineIntegration({
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	name&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;astro-integration-hello&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	setup() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;		&lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;			hooks&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;:&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;				&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;astro:config:setup&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;:&lt;/span&gt; (options) =&amp;gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;					options.injectScript(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;						&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;page&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;						&lt;span style=&#34;color:#a6da95&#34;&gt;`console.log(&amp;#34;test this!&amp;#34;);`&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;					)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;					logServerMessage(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Integration Happened&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;				}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;				
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;			},
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;		};
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	},
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;});
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;scriptssupport_scriptts&#34;&gt;scripts/support_script.ts&lt;/h3&gt;
&lt;p&gt;This file is specifically not named the same as the exported entry point to make it clear that the entry point is how the client package is accessing the code.&lt;/p&gt;
&lt;p&gt;started with vanilla javascript from the &lt;a href=&#34;https://github.com/understanding-astro/understanding-astro-book/blob/master/ch8.md&#34;&gt;Understanding Astro: Integrations&lt;/a&gt; example.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-javascript&#34; data-lang=&#34;javascript&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;const&lt;/span&gt; logger &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; () =&amp;gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#c6a0f6&#34;&gt;const&lt;/span&gt; msg &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Hello Integrations&amp;#34;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  console.log(&lt;span style=&#34;color:#a6da95&#34;&gt;`%c &lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;${&lt;/span&gt;msg&lt;span style=&#34;color:#a6da95&#34;&gt;}&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;`&lt;/span&gt;, &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;background: black;  color: yellow&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;};
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;logger();
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description>
    </item>
    
    
    
    <item>
      <title>Checking typed errors with swift-testing</title>
      <link>https://whynotestflight.com/excuses/checking-typed-errors-with-swift-testing/</link>
      <pubDate>Mon, 26 May 2025 00:00:00 +0000</pubDate>
      
      <guid>https://whynotestflight.com/excuses/checking-typed-errors-with-swift-testing/</guid>
      <description>&lt;p&gt;It seems reasonable at this point to put all my file-wrangling knowledge in a reusable package so I&amp;rsquo;m not reinventing the wheel every time. Every project needs something a little bit different, so even if I pirate files or functions out, at least there will be one place to look.&lt;/p&gt;
&lt;p&gt;Since in one of my projects I already had some &lt;code&gt;XCTests&lt;/code&gt;, I&amp;rsquo;m using this as a chance to migrate over to &lt;code&gt;swift-testing&lt;/code&gt; as well.  When watching the &lt;a href=&#34;https://developer.apple.com/videos/play/wwdc2024/10195&#34;&gt;WWDC video&lt;/a&gt; it mentioned that one should also be writing tests for&amp;quot;unhappy paths&amp;quot;. An obviously good thing to do which I have not been doing!&lt;/p&gt;
&lt;p&gt;So I started playing around with watching for the &lt;em&gt;right&lt;/em&gt; error messages with &lt;code&gt;swift-testing&lt;/code&gt;&lt;/p&gt;
&lt;h2 id=&#34;resources&#34;&gt;Resources&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://developer.apple.com/documentation/testing&#34;&gt;https://developer.apple.com/documentation/testing&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;2024 &amp;ldquo;Go Further&amp;rdquo; video &lt;a href=&#34;https://developer.apple.com/videos/play/wwdc2024/10195&#34;&gt;https://developer.apple.com/videos/play/wwdc2024/10195&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://oleb.net/2023/catch-error-code/&#34;&gt;https://oleb.net/2023/catch-error-code/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://www.hackingwithswift.com/new-syntax-swift-2-error-handling-try-catch&#34;&gt;https://www.hackingwithswift.com/new-syntax-swift-2-error-handling-try-catch&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://forums.swift.org/t/swift-testing-and-errors-with-associated-types/79969/&#34;&gt;https://forums.swift.org/t/swift-testing-and-errors-with-associated-types/79969/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://forums.swift.org/t/comparing-enum-cases-while-ignoring-associated-values/15922/24&#34;&gt;https://forums.swift.org/t/comparing-enum-cases-while-ignoring-associated-values/15922/24&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;general-error-catching&#34;&gt;General Error Catching&lt;/h2&gt;
&lt;p&gt;First I have my errors that I want to try to catch. They have to conform to equitable in order for me to test for them using the &lt;code&gt;#expect&lt;/code&gt; macro the way I want to.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;enum&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;ExampleError&lt;/span&gt;:Error {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;case&lt;/span&gt; unknownError(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; message: &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;case&lt;/span&gt; codedError(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; code:&lt;span style=&#34;color:#91d7e3&#34;&gt;Int&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;case&lt;/span&gt; noExtras
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;extension&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;ExampleError&lt;/span&gt;:&lt;span style=&#34;color:#91d7e3&#34;&gt;Equatable&lt;/span&gt; {}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Then I have the struct to test. I am using async functions since that is the harder case, but this all works with synchronous functions as well.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;TestMe&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;throwsMessage&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; message:&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;) async &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;throw&lt;/span&gt; ExampleError.unknownError(message)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;throwsCode&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; codeToThrow:&lt;span style=&#34;color:#91d7e3&#34;&gt;Int&lt;/span&gt;) async &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;throw&lt;/span&gt; ExampleError.codedError(codeToThrow)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;throwsSimple&lt;/span&gt;() async &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;throw&lt;/span&gt; ExampleError.noExtras
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;no-associated-type&#34;&gt;No associated type&lt;/h3&gt;
&lt;p&gt;The very first test function, one where it catches an error with no associated value is pretty easy:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//use in all the tests as part of a suite&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;itemToTest&lt;/span&gt;:TestMe = TestMe()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    @Test &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;simpleErrorTest&lt;/span&gt;() async &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//required explicit equatable&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        await #expect(&lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt;: ExampleError.noExtras) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; await itemToTest.throwsSimple()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;associated-values-with-known-values-to-test-against&#34;&gt;Associated values with known values to test against.&lt;/h3&gt;
&lt;p&gt;Things get a little messier when I want to test against the &lt;code&gt;Error&lt;/code&gt;&amp;rsquo;s subtype.&lt;/p&gt;
&lt;p&gt;When the value is known that is also easy, but to retrieve the value and test requires finding a way to pull it out with a &lt;code&gt;case&lt;/code&gt; statement.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    @Test &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;testForExpectedCode&lt;/span&gt;() async &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;expectedCode&lt;/span&gt; = &lt;span style=&#34;color:#f5a97f&#34;&gt;42&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//when you know the exact code, everything is fine.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        await #expect(&lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt;: ExampleError.codedError(expectedCode)) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; await itemToTest.throwsCode(expectedCode)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;allowedRange&lt;/span&gt; = (&lt;span style=&#34;color:#f5a97f&#34;&gt;20.&lt;/span&gt;..&lt;span style=&#34;color:#f5a97f&#34;&gt;49&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        await #expect {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; await itemToTest.throwsCode(expectedCode)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        } &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt;: { error &lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;guard&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;error&lt;/span&gt; = error &lt;span style=&#34;color:#c6a0f6&#34;&gt;as&lt;/span&gt;? ExampleError &lt;span style=&#34;color:#c6a0f6&#34;&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;false&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;switch&lt;/span&gt; error {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;case&lt;/span&gt; .codedError(&lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;code&lt;/span&gt;):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; allowedRange.&lt;span style=&#34;color:#91d7e3&#34;&gt;contains&lt;/span&gt;(code)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;default&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;false&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;That seemed long and like I was missing something, so asked on the &lt;a href=&#34;https://forums.swift.org/t/swift-testing-and-errors-with-associated-types/79969/&#34;&gt;forums for some help&lt;/a&gt;. I used the advice to formulate:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    @Test &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;testForExpectedCodeV2&lt;/span&gt;() async &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;expectedCode&lt;/span&gt; = &lt;span style=&#34;color:#f5a97f&#34;&gt;42&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//demoing require keyword, not strictly necessary here. &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;error&lt;/span&gt; = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; await #require(&lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt;: ExampleError.&lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; await itemToTest.throwsCode(expectedCode)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        #expect(error == .codedError(expectedCode))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        #expect(await errorContainedIn(range: &lt;span style=&#34;color:#f5a97f&#34;&gt;20.&lt;/span&gt;..&lt;span style=&#34;color:#f5a97f&#34;&gt;49&lt;/span&gt;, 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                                       with: &lt;span style=&#34;color:#91d7e3&#34;&gt;Int&lt;/span&gt;.random(&lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt;: &lt;span style=&#34;color:#f5a97f&#34;&gt;20.&lt;/span&gt;..&lt;span style=&#34;color:#f5a97f&#34;&gt;49&lt;/span&gt;), 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                                       from: itemToTest.throwsCode))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;errorContainedIn&lt;/span&gt;(range:ClosedRange&amp;lt;&lt;span style=&#34;color:#91d7e3&#34;&gt;Int&lt;/span&gt;&amp;gt;, with:&lt;span style=&#34;color:#91d7e3&#34;&gt;Int&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            from function:(&lt;span style=&#34;color:#91d7e3&#34;&gt;Int&lt;/span&gt;) async &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; -&amp;gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;Void&lt;/span&gt;) async -&amp;gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;Bool&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//but cannot use require here because has to be failable for guard-case &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;guard&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;case&lt;/span&gt; .codedError(&lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;code&lt;/span&gt;) = (await #expect(&lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt;: ExampleError.&lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; await function(with)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            }) &lt;span style=&#34;color:#c6a0f6&#34;&gt;else&lt;/span&gt; { &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;false&lt;/span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; range.&lt;span style=&#34;color:#91d7e3&#34;&gt;contains&lt;/span&gt;(code)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Nice reusable function that I can lift to the top of the suite.&lt;/p&gt;
&lt;h3 id=&#34;trying-to-ignore-the-associated-value&#34;&gt;Trying to ignore the associated value&lt;/h3&gt;
&lt;p&gt;Ignoring the associated type&amp;rsquo;s value was still pretty verbose my first pass.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    @Test &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;testForAnyCode&lt;/span&gt;() async &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;         &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//Can&amp;#39;t find the right way to frame this? Is it possible?&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;         &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// ExampleError.codedError is not a _Type_&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;         &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// #expect(throws: ExampleError.codedError(_)) {&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;         &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//     try await throwsCode(Int.random(in: 0...5))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;         &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// }&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        await #expect {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; await itemToTest.throwsCode(&lt;span style=&#34;color:#91d7e3&#34;&gt;Int&lt;/span&gt;.random(&lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt;: &lt;span style=&#34;color:#f5a97f&#34;&gt;0.&lt;/span&gt;..&lt;span style=&#34;color:#f5a97f&#34;&gt;5&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        } &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt;: { error &lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;guard&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;error&lt;/span&gt; = error &lt;span style=&#34;color:#c6a0f6&#34;&gt;as&lt;/span&gt;? ExampleError &lt;span style=&#34;color:#c6a0f6&#34;&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;false&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;switch&lt;/span&gt; error {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;case&lt;/span&gt; .codedError(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt;):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;default&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;false&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;First thing I did was add a function to the enum that honestly would have been annoying to maintain because it would need to be done for every case with an associated value.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;isCodedError&lt;/span&gt;() -&amp;gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;Bool&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;switch&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;case&lt;/span&gt; .codedError(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt;):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;default&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;false&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Which leads to a much shorter test, but a lot of down the road hassle on the error enum.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    @Test &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;testForAnyCodeV2&lt;/span&gt;() async &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;error&lt;/span&gt; = await #expect(&lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt;: ExampleError.&lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; await itemToTest.throwsCode(&lt;span style=&#34;color:#91d7e3&#34;&gt;Int&lt;/span&gt;.random(&lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt;: &lt;span style=&#34;color:#f5a97f&#34;&gt;0.&lt;/span&gt;..&lt;span style=&#34;color:#f5a97f&#34;&gt;5&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        #expect(error?.isCodedError() == &lt;span style=&#34;color:#f5a97f&#34;&gt;true&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;On a &lt;a href=&#34;https://forums.swift.org/t/comparing-enum-cases-while-ignoring-associated-values/15922/24&#34;&gt;different forum thread&lt;/a&gt; someone else posted something along the lines of&amp;hellip;&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;MARK:&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt; Error Extension&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;Foundation&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;extension&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;Error&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;discriminator&lt;/span&gt;:&lt;span style=&#34;color:#91d7e3&#34;&gt;Int&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        (&lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;as&lt;/span&gt; NSError).code
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;@Test &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;testForAnyCodeV3&lt;/span&gt;() async &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;error&lt;/span&gt; = await #expect(&lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt;: ExampleError.&lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; await itemToTest.throwsCode(&lt;span style=&#34;color:#91d7e3&#34;&gt;Int&lt;/span&gt;.random(&lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt;: &lt;span style=&#34;color:#f5a97f&#34;&gt;0.&lt;/span&gt;..&lt;span style=&#34;color:#f5a97f&#34;&gt;5&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//the presence of an actual number could be confusing if it is arbitrary&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//let typeCodeForCodedError = ExampleError.codedError(3213).discriminator&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;typeCodeForCodedError&lt;/span&gt; = &lt;span style=&#34;color:#f5a97f&#34;&gt;1&lt;/span&gt; &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//better never change the order of your enum if use this though. &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    #expect(error?.discriminator == typeCodeForCodedError)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&amp;hellip; which I have mixed feeling about because it requires &lt;code&gt;Foundation&lt;/code&gt; and to jump through some minor hoops to get the right value for the error (see code comments.)&lt;/p&gt;
&lt;p&gt;See the &lt;a href=&#34;https://github.com/carlynorama/SwiftTestingExplorer&#34;&gt;demo repo&lt;/a&gt; for all the tests.&lt;/p&gt;
&lt;h2 id=&#34;catching-errors-that-dont-belong-to-me&#34;&gt;Catching errors that don&amp;rsquo;t belong to me&lt;/h2&gt;
&lt;p&gt;In the actual &lt;a href=&#34;https://github.com/carlynorama/FileWrangler&#34;&gt;&lt;code&gt;FileWrangler&lt;/code&gt;&lt;/a&gt; code I want all my missing files to throw the same error, a &lt;code&gt;FileServiceError.noFileAtLocation(_ path: String)&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;So the test for that  might look like:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        @Test(.tags(.existing)) &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;tryToDeleteNonExistentFile&lt;/span&gt;() async &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;fileToTestPath&lt;/span&gt; = touchPractice
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;fileToTest&lt;/span&gt; = FWFile(path: fileToTestPath)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;expectedErrorMessage&lt;/span&gt; = &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;FileID not associated with deletable file.&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;error&lt;/span&gt; = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; await #require(&lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt;: FileServiceError.&lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; await fileServiceToTest.delete(fileToTest)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(error)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            #expect(allowedError(error))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;postExists&lt;/span&gt; = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; await fileServiceToTest.locationExists(&lt;span style=&#34;color:#c6a0f6&#34;&gt;for&lt;/span&gt;: fileToTest)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            #expect(&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;!&lt;/span&gt;postExists)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;allowedError&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; error:FileServiceError) -&amp;gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;Bool&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#c6a0f6&#34;&gt;switch&lt;/span&gt; error {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#c6a0f6&#34;&gt;case&lt;/span&gt; .noFileAtLocation(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt;): &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#c6a0f6&#34;&gt;case&lt;/span&gt; .unknownError(&lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;message&lt;/span&gt;):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; message == expectedErrorMessage
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#c6a0f6&#34;&gt;default&lt;/span&gt;: &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;false&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;But the problem is that my &lt;code&gt;fileServiceToTest.delete(fileToTest)&lt;/code&gt; doesn&amp;rsquo;t throw MY error, it throws an error from the system.&lt;/p&gt;
&lt;p&gt;I found a great article on &lt;a href=&#34;https://oleb.net/2023/catch-error-code/&#34;&gt;catching CocoaErrors&lt;/a&gt; so now my delete function re-skins that error:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;delete&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; id: FWFile) async &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;path&lt;/span&gt; = id.locationPath
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//let url = id.locationURL&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//note returns true if file does not exist. &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//appears to be essentially a permissions check.  &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;guard&lt;/span&gt; fileManager.isDeletableFile(atPath: path) &lt;span style=&#34;color:#c6a0f6&#34;&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;throw&lt;/span&gt; FileServiceError(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;FileID not associated with deletable file.&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;do&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; fileManager.removeItem(atPath: path)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        } &lt;span style=&#34;color:#c6a0f6&#34;&gt;catch&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;error&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;as&lt;/span&gt; CocoaError &lt;span style=&#34;color:#c6a0f6&#34;&gt;where&lt;/span&gt; error.code == .fileNoSuchFile {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;throw&lt;/span&gt; FileServiceError.noFileAtLocation(path)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        } &lt;span style=&#34;color:#c6a0f6&#34;&gt;catch&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;throw&lt;/span&gt; FileServiceError.caughtError(error)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description>
    </item>
    
    
    
    <item>
      <title>SwiftData, my first look</title>
      <link>https://whynotestflight.com/excuses/swiftdata-my-first-look/</link>
      <pubDate>Mon, 05 May 2025 00:00:00 +0000</pubDate>
      
      <guid>https://whynotestflight.com/excuses/swiftdata-my-first-look/</guid>
      <description>&lt;p&gt;SwiftData seems to be a very good fit for simple projects. When using defaults developers get a lot of features right out of the gate, like change history and undo. Default settings also syncs across devices easily with CloudKit, with a few caveats.&lt;/p&gt;
&lt;p&gt;In 2024 Apple added a &lt;code&gt;DataStore&lt;/code&gt; protocol so you can swap in your own preferred persistence style, rather than the very fancy wrapper around SQLite that it comes with out of the box.&lt;/p&gt;
&lt;h3 id=&#34;resources&#34;&gt;Resources&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://www.hackingwithswift.com/quick-start/swiftdata&#34;&gt;https://www.hackingwithswift.com/quick-start/swiftdata&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://developer.apple.com/videos/play/wwdc2023/10187/&#34;&gt;https://developer.apple.com/videos/play/wwdc2023/10187/&lt;/a&gt; (2023 - Meet SwiftData)&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://developer.apple.com/videos/play/wwdc2024/10137/&#34;&gt;https://developer.apple.com/videos/play/wwdc2024/10137/&lt;/a&gt; (2024 - What&amp;rsquo;s new in SwiftData)&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://developer.apple.com/videos/play/wwdc2024/10138&#34;&gt;https://developer.apple.com/videos/play/wwdc2024/10138&lt;/a&gt;  (2024 - Create a custom data store with SwiftData)&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://developer.apple.com/videos/play/wwdc2023/10196&#34;&gt;https://developer.apple.com/videos/play/wwdc2023/10196&lt;/a&gt;  (2023 - Dive deeper into SwiftData)&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://developer.apple.com/xcode/swiftdata/&#34;&gt;https://developer.apple.com/xcode/swiftdata/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://www.hackingwithswift.com/quick-start/swiftdata/whats-the-difference-between-modelcontainer-modelcontext-and-modelconfiguration&#34;&gt;https://www.hackingwithswift.com/quick-start/swiftdata/whats-the-difference-between-modelcontainer-modelcontext-and-modelconfiguration&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;the-pieces&#34;&gt;The pieces&lt;/h2&gt;
&lt;p&gt;After going through some basic hello world tutorials/intro WWDC videos, definitely do watch the 2023 &lt;a href=&#34;https://developer.apple.com/videos/play/wwdc2023/10196&#34;&gt;Dive Deeper&lt;/a&gt; video to understand how the parts work together.&lt;/p&gt;
&lt;h3 id=&#34;schema&#34;&gt;Schema&lt;/h3&gt;
&lt;p&gt;If this word is unfamiliar to you: &lt;a href=&#34;https://en.wikipedia.org/wiki/Database_schema&#34;&gt;https://en.wikipedia.org/wiki/Database_schema&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;@Model&lt;/code&gt;&amp;lsquo;ing classes in your code is how &lt;code&gt;SwiftData&lt;/code&gt; adds what it needs to use those classes to build a schema. There are a couple of ways to set up a &lt;code&gt;Schema&lt;/code&gt; type. The fast way when there is only one class is just to give that &lt;code&gt;@Model&lt;/code&gt; decorated class to the simple &lt;code&gt;ModelContainer&lt;/code&gt; view modifier style init.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;@Model
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;final&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;MyModelType&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;item&lt;/span&gt;:Item?
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;init&lt;/span&gt;(item:Item) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;.item = item
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;SomeView().modelContainer(&lt;span style=&#34;color:#c6a0f6&#34;&gt;for&lt;/span&gt;: MyModelType.&lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;, inMemory: &lt;span style=&#34;color:#f5a97f&#34;&gt;true&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Expanding that macro adds the following code:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;Foundation&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;SwiftData&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;final&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;MyModelType&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    @_PersistedProperty &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;item&lt;/span&gt;:Item?
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;init&lt;/span&gt;(textInfo: &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;, timestamp: Date) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;.item = Item(textInfo: textInfo, timestamp: timestamp)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    @Transient
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;private&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;_&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;$&lt;/span&gt;backingData: any SwiftData.BackingData&amp;lt;MyModelType&amp;gt; = MyModelType.createBackingData()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;persistentBackingData&lt;/span&gt;: any SwiftData.BackingData&amp;lt;MyModelType&amp;gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;get&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;$&lt;/span&gt;backingData
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;set&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;$&lt;/span&gt;backingData = newValue
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;schemaMetadata&lt;/span&gt;: [SwiftData.Schema.PropertyMetadata] {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; [
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            SwiftData.Schema.PropertyMetadata(name: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;item&amp;#34;&lt;/span&gt;, keypath: &lt;span style=&#34;color:#ed8796&#34;&gt;\&lt;/span&gt;MyModelType.item, defaultValue: &lt;span style=&#34;color:#f5a97f&#34;&gt;nil&lt;/span&gt;, metadata: &lt;span style=&#34;color:#f5a97f&#34;&gt;nil&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        ]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;init&lt;/span&gt;(backingData: any SwiftData.BackingData&amp;lt;MyModelType&amp;gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        _item = _SwiftDataNoType()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;.persistentBackingData = backingData
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    @Transient &lt;span style=&#34;color:#ed8796&#34;&gt;private&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;_&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;$&lt;/span&gt;observationRegistrar = Observation.ObservationRegistrar()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;internal&lt;/span&gt; nonisolated &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;access&lt;/span&gt;&amp;lt;_M&amp;gt;(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        keyPath: KeyPath&amp;lt;MyModelType, _M&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    ) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;$&lt;/span&gt;observationRegistrar.access(&lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;, keyPath: keyPath)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;internal&lt;/span&gt; nonisolated &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;withMutation&lt;/span&gt;&amp;lt;_M, _MR&amp;gt;(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        keyPath: KeyPath&amp;lt;MyModelType, _M&amp;gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; mutation: () &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; -&amp;gt; _MR
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    ) &lt;span style=&#34;color:#c6a0f6&#34;&gt;rethrows&lt;/span&gt; -&amp;gt; _MR {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;$&lt;/span&gt;observationRegistrar.withMutation(of: &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;, keyPath: keyPath, mutation)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;_SwiftDataNoType&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;extension&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;MyModelType&lt;/span&gt;: SwiftData.PersistentModel {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;extension&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;MyModelType&lt;/span&gt;: Observation.Observable {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Note the conformance to &lt;code&gt;Observation.Observable&lt;/code&gt; at the end there, which is part of how &lt;code&gt;SwiftData&lt;/code&gt; works so seamlessly with SwiftUI.&lt;/p&gt;
&lt;p&gt;If there will be more than one class as part of the schema one can declare a &lt;code&gt;Schema&lt;/code&gt; type explicitly by giving it an array of all the relevant macro&amp;rsquo;ed types.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;schema&lt;/span&gt; = Schema([
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            MyModelType.&lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;, MyHelperType.&lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        ])
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;modelConfiguration&lt;/span&gt; = ModelConfiguration(schema: schema, isStoredInMemoryOnly: &lt;span style=&#34;color:#f5a97f&#34;&gt;false&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;glue-layer-between-models-and-persistence&#34;&gt;Glue Layer Between Models and Persistence&lt;/h3&gt;
&lt;p&gt;So whole point of using &lt;code&gt;SwiftData&lt;/code&gt; is to persist the data associated with the models across app launches.  There needs to be code that moves the information between active use and persistent storage and vice versa. In &lt;code&gt;SwiftData&lt;/code&gt; the &lt;a href=&#34;https://developer.apple.com/documentation/swiftdata/modelcontainer&#34;&gt;&lt;code&gt;ModelContainer&lt;/code&gt;&lt;/a&gt; hold the description of how that data will be saved and retrieved.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;ModelContainer&lt;/code&gt; has a configuration type &lt;a href=&#34;https://developer.apple.com/documentation/swiftdata/modelconfiguration&#34;&gt;&lt;code&gt;ModelConfiguration&lt;/code&gt;&lt;/a&gt; with several initializers like the two below:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ModelConfiguration(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; name: &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;?, 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    schema: Schema?, 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    isStoredInMemoryOnly: &lt;span style=&#34;color:#91d7e3&#34;&gt;Bool&lt;/span&gt;, 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    allowsSave: &lt;span style=&#34;color:#91d7e3&#34;&gt;Bool&lt;/span&gt;, 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    groupContainer: ModelConfiguration.GroupContainer, 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    cloudKitDatabase: ModelConfiguration.CloudKitDatabase)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ModelConfiguration(&amp;lt;name: &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;?, 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    schema: Schema?, 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    url: URL, 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    allowsSave: &lt;span style=&#34;color:#91d7e3&#34;&gt;Bool&lt;/span&gt;, 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    cloudKitDatabase: ModelConfiguration.CloudKitDatabase)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;One can instantiate a model container using a &lt;code&gt;Schema&lt;/code&gt; and an array of configurations:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; ModelContainer(&lt;span style=&#34;color:#c6a0f6&#34;&gt;for&lt;/span&gt;: schema, configurations: [modelConfiguration])
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This initializer can fail because some aspect of what you&amp;rsquo;re telling the &lt;code&gt;ModelContainer&lt;/code&gt; to believe about the persistence layer could end up being wrong. The file location could not exist. The code could not have permission to change the file, etc.&lt;/p&gt;
&lt;p&gt;That&amp;rsquo;s in contrast to the convenience initializer that uses the default data store as the basis of its assumed configuration. (recall: &lt;code&gt;SomeView().modelContainer(for: MyModelType.self, inMemory: true)&lt;/code&gt;)&lt;/p&gt;
&lt;p&gt;Once the &lt;code&gt;ModelContainer&lt;/code&gt; gets created it gets passed into an App&amp;rsquo;s &lt;a href=&#34;https://developer.apple.com/documentation/swiftdata/modelcontext/&#34;&gt;&lt;code&gt;ModelContext&lt;/code&gt;&lt;/a&gt;. The &lt;code&gt;ModelContext&lt;/code&gt; does the actually pretty darn fancy footwork of moving information between the active processes and the data storage. For example, if with every little change of information the program was constantly writing to disk the code would end up being very slow. The &lt;code&gt;ModelContext&lt;/code&gt; batches the changes, balancing speed and safety.&lt;/p&gt;
&lt;h2 id=&#34;make-a-struct-and-a-matching-model&#34;&gt;Make a struct and a matching model&lt;/h2&gt;
&lt;p&gt;The easiest way to check out &lt;code&gt;SwiftData&lt;/code&gt; would be be to create a new project with &lt;code&gt;SwiftData&lt;/code&gt; the &lt;code&gt;CloudKit&lt;/code&gt; options selected. But following the HWS example listed in the references up top, Paul Hudson takes you through the process from the beginning. That tutorial is way more complete than these notes. Follow that. As are the WWDC videos. Watch those.&lt;/p&gt;
&lt;p&gt;When looking at tutorials what one will see is that everyone makes their model a class when using &lt;code&gt;SwiftData&lt;/code&gt;. And when that class is going to be used with &lt;code&gt;CloudKit&lt;/code&gt;, each parameter has to be optional or have a default value. This helps the code know how to resolve when connections fail.&lt;/p&gt;
&lt;p&gt;However that&amp;rsquo;s kind of annoying if one wants use structs for your data type. When writing a project without &lt;code&gt;SwiftData&lt;/code&gt; I have typically used structs for my models and an &lt;code&gt;Actor&lt;/code&gt; for my DataStore and protocol based &lt;code&gt;PersistenceService&lt;/code&gt; to save the data.&lt;/p&gt;
&lt;p&gt;I will have to change how I work to use &lt;code&gt;SwiftData&lt;/code&gt;, but I wanted to see how keeping structs in the mix might still work.&lt;/p&gt;
&lt;p&gt;I tried three different approaches.&lt;/p&gt;
&lt;h3 id=&#34;approach-1-class-wrapper-for-the-struct&#34;&gt;Approach 1: Class wrapper for the struct&lt;/h3&gt;
&lt;p&gt;One approach uses the &lt;code&gt;SwiftData&lt;/code&gt; model class as a thin wrapper around a struct. &amp;ldquo;Business logic&amp;rdquo; code interacts with the struct, and the UI code selects a record via the class&amp;rsquo;s code and then pulls out the underlying struct to render, update or access business logic.&lt;/p&gt;
&lt;p&gt;Since my interest is working with &lt;code&gt;CloudKit&lt;/code&gt;, this example shows having the struct be an Optional in the class.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;Foundation&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;SwiftData&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;Foundation&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;Item&lt;/span&gt;:Sendable, Codable, &lt;span style=&#34;color:#91d7e3&#34;&gt;Hashable&lt;/span&gt;, &lt;span style=&#34;color:#91d7e3&#34;&gt;Equatable&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;textInfo&lt;/span&gt;:&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;timestamp&lt;/span&gt;:Date
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;displayMe&lt;/span&gt;:&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;textInfo&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt; at &lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;timestamp.formatted&lt;span style=&#34;color:#a6da95&#34;&gt;(&lt;/span&gt;date: .long, time: .shortened&lt;span style=&#34;color:#a6da95&#34;&gt;))&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;extension&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;Item&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;init&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; text:&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;.&lt;span style=&#34;color:#ed8796&#34;&gt;init&lt;/span&gt;(textInfo: text, timestamp: .now)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;init&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;.&lt;span style=&#34;color:#ed8796&#34;&gt;init&lt;/span&gt;(textInfo: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Very important information!!!&amp;#34;&lt;/span&gt;, timestamp: .now)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;@Model
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;final&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;ItemSDMC&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;item&lt;/span&gt;:Item?
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;init&lt;/span&gt;(textInfo: &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;, timestamp: Date) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;.item = Item(textInfo: textInfo, timestamp: timestamp)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;extension&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;ItemSDMC&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;convenience&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;init&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; text:&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;.&lt;span style=&#34;color:#ed8796&#34;&gt;init&lt;/span&gt;(textInfo: text, timestamp: .now)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;convenience&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;init&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;.&lt;span style=&#34;color:#ed8796&#34;&gt;init&lt;/span&gt;(textInfo: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Very important information!!!&amp;#34;&lt;/span&gt;, timestamp: .now)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//  EditItemView.swift&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//  DataFling&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;SwiftUI&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;EditItemView&lt;/span&gt;: View {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    @Bindable &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;sdModelItem&lt;/span&gt;:ItemSDMC
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    @State &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;nonOptionalItemHolder&lt;/span&gt;:Item
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;init&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; item: ItemSDMC) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;.sdModelItem = item
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;wrapped&lt;/span&gt; = item.item {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            nonOptionalItemHolder = wrapped
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        } &lt;span style=&#34;color:#c6a0f6&#34;&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            nonOptionalItemHolder = Item(textInfo: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Empty Item&amp;#34;&lt;/span&gt;, timestamp: Date())
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;body&lt;/span&gt;: some View {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;boundItem&lt;/span&gt; = Binding(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;get&lt;/span&gt;: {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                _nonOptionalItemHolder.wrappedValue
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            },
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;set&lt;/span&gt;: {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//Note this should never happen in this view because&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//is ItemSDMC somehow returns a nil Item, no edit view will&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//be displayed.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;$0&lt;/span&gt;.textInfo &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;!=&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;EmptyItem&amp;#34;&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    nonOptionalItemHolder = &lt;span style=&#34;color:#f4dbd6&#34;&gt;$0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    sdModelItem.item = &lt;span style=&#34;color:#f4dbd6&#34;&gt;$0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                } &lt;span style=&#34;color:#c6a0f6&#34;&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    &lt;span style=&#34;color:#91d7e3&#34;&gt;fatalError&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;How did an Empty Item get sent to be updated?&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        )
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        VStack {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; sdModelItem.item &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;!=&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;nil&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                Text(sdModelItem.item!.displayMe)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                Form {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    TextField(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;text&amp;#34;&lt;/span&gt;, text:boundItem.textInfo)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    DatePicker(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Date&amp;#34;&lt;/span&gt;, selection: boundItem.timestamp)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            } &lt;span style=&#34;color:#c6a0f6&#34;&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                Text(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;There has been an mistake. This item has no data&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#if&lt;/span&gt; &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;os&lt;/span&gt;(&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;iOS&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        .navigationTitle(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Edit Item&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        .navigationBarTitleDisplayMode(.inline)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#endif&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;#Preview {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    @Previewable &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;myItem&lt;/span&gt; = ItemSDMC(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Example Item for Preview&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    EditItemView(myItem)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Discussions on how to handle bindings:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://www.hackingwithswift.com/quick-start/swiftui/how-to-create-custom-bindings&#34;&gt;https://www.hackingwithswift.com/quick-start/swiftui/how-to-create-custom-bindings&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://forums.swift.org/t/passing-custom-getter-and-setter-to-property-wrapper-initializer/32000/6&#34;&gt;https://forums.swift.org/t/passing-custom-getter-and-setter-to-property-wrapper-initializer/32000/6&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://stackoverflow.com/questions/69762157/how-to-use-setter-of-custom-swiftui-binding-after-value-conversion&#34;&gt;https://stackoverflow.com/questions/69762157/how-to-use-setter-of-custom-swiftui-binding-after-value-conversion&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;approach-2-keep-the-struct-dumb&#34;&gt;Approach 2: Keep the struct dumb&lt;/h3&gt;
&lt;p&gt;This approach differs because both the class and the struct have all the fields, and also because the class would contain the business logic and the struct would be a fairly dumb data structure.&lt;/p&gt;
&lt;p&gt;Since my interest is working with &lt;code&gt;CloudKit&lt;/code&gt;, this example shows having each parameter having a default value, the other choice being to use optionals like in the previous approach.&lt;/p&gt;
&lt;p&gt;One of the advantages of this approach is that the newish &lt;code&gt;Observation.Observable&lt;/code&gt; protocol has more granularity than what you could do before, i.e. an update to one parameter won&amp;rsquo;t trigger updates unless that parameter is in fact &lt;a href=&#34;https://developer.apple.com/videos/play/wwdc2023/10149/&#34;&gt;being observed by something active in the program&lt;/a&gt;.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;Foundation&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;SwiftData&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;ThingLite&lt;/span&gt;:Sendable, Codable, &lt;span style=&#34;color:#91d7e3&#34;&gt;Hashable&lt;/span&gt;, &lt;span style=&#34;color:#91d7e3&#34;&gt;Equatable&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;textInfo&lt;/span&gt;:&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;timestamp&lt;/span&gt;:Date
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;@Model
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;final&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;Thing&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//using this default value requires writing some clean up logic looking for empty text info.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;textInfo&lt;/span&gt;:&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt; = &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//using this default value would require writing some data clean up functions looking for out of bound dates.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;timestamp&lt;/span&gt;:Date = Date.distantPast
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;init&lt;/span&gt;(textInfo: &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;, timestamp: Date) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;.textInfo = textInfo
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;.timestamp = timestamp
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;displayMe&lt;/span&gt;:&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;textInfo&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt; at &lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;timestamp.formatted&lt;span style=&#34;color:#a6da95&#34;&gt;(&lt;/span&gt;date: .long, time: .shortened&lt;span style=&#34;color:#a6da95&#34;&gt;))&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;liteCopy&lt;/span&gt;:ThingLite {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        ThingLite(textInfo: textInfo, timestamp: timestamp)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;liteCopyWithID&lt;/span&gt;:(data:ThingLite, id:PersistentIdentifier) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//(sendableCopy, id) also works&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        (sendableCopy, persistentModelID)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//  EditThingView.swift&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//  DataFling&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;SwiftUI&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;EditThingView&lt;/span&gt;: View {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    @Bindable &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;thing&lt;/span&gt;:Thing
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;body&lt;/span&gt;: some View {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        VStack {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            Text(thing.displayMe)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            Form {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                TextField(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;text&amp;#34;&lt;/span&gt;, text:&lt;span style=&#34;color:#ed8796&#34;&gt;$&lt;/span&gt;thing.textInfo)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                DatePicker(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Date&amp;#34;&lt;/span&gt;, selection: &lt;span style=&#34;color:#ed8796&#34;&gt;$&lt;/span&gt;thing.timestamp)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }.task {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            await doSomeAsyncThing(thing:thing)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#if&lt;/span&gt; &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;os&lt;/span&gt;(&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;iOS&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        .navigationTitle(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Edit Item&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        .navigationBarTitleDisplayMode(.inline)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#endif&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;doSomeAsyncThing&lt;/span&gt;(thing:Thing) async {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(thing.liteCopy)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;#Preview {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    @Previewable &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;myThing&lt;/span&gt; = Thing(textInfo:&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Example for Preview&amp;#34;&lt;/span&gt;, timestamp: Date())
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    EditThingView(thing: myThing)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://fatbobman.com/en/posts/nsmanagedobjectid-and-persistentidentifier/&#34;&gt;https://fatbobman.com/en/posts/nsmanagedobjectid-and-persistentidentifier/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;third-approach-protocol&#34;&gt;Third Approach: Protocol&lt;/h3&gt;
&lt;p&gt;The third approach is to use a protocol as the main basic for all the business logic. I won&amp;rsquo;t get into that too much now because its the one I&amp;rsquo;m going to be trying out for a bit.&lt;/p&gt;
&lt;p&gt;It might look a little something like the below, although there is still things to work out about how ID would work.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;Foundation&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;SwiftData&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;protocol&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;Thingable&lt;/span&gt;:Identifiable {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;textInfo&lt;/span&gt;:&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt; { &lt;span style=&#34;color:#c6a0f6&#34;&gt;get&lt;/span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;timestamp&lt;/span&gt;:Date { &lt;span style=&#34;color:#c6a0f6&#34;&gt;get&lt;/span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;extension&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;Thingable&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;thingDisplay&lt;/span&gt;:&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;textInfo&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt; with &lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;id&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt; at &lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;timestamp.formatted&lt;span style=&#34;color:#a6da95&#34;&gt;(&lt;/span&gt;date: .long, time: .shortened&lt;span style=&#34;color:#a6da95&#34;&gt;))&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;extension&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;Thingable&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;where&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;Self&lt;/span&gt;:PersistentModel {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;thingDisplayWithID&lt;/span&gt;:&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;textInfo&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt; with modelID &lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;&lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;.persistentModelID.id&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt; in &lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;(&lt;/span&gt;describing: &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;.persistentModelID.storeIdentifier&lt;span style=&#34;color:#a6da95&#34;&gt;))&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt; at &lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;timestamp.formatted&lt;span style=&#34;color:#a6da95&#34;&gt;(&lt;/span&gt;date: .long, time: .shortened&lt;span style=&#34;color:#a6da95&#34;&gt;))&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;ThingLite&lt;/span&gt;:Thingable, Codable, Sendable {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;textInfo&lt;/span&gt;: &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;timestamp&lt;/span&gt;: Date
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;id&lt;/span&gt;: &lt;span style=&#34;color:#91d7e3&#34;&gt;Int&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;@Model
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;final&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;Thing&lt;/span&gt;:Thingable {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//using this default value requires writng some clean up logic looking for empty text info.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;textInfo&lt;/span&gt;:&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt; = &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//using this default value would require writing some data clean up functions looking for out of bound dates.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;timestamp&lt;/span&gt;:Date = Date.distantPast
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;init&lt;/span&gt;(textInfo: &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;, timestamp: Date) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;.textInfo = textInfo
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;.timestamp = timestamp
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;extension&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;Thing&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;LiteThing&lt;/span&gt;:ThingLite {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        ThingLite(textInfo: textInfo, timestamp: timestamp, id: persistentModelID.hashValue)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;If one goes that route, at least as of May 2025, it is ill advised to try to make a generic view that takes in &lt;code&gt;some Thingable&lt;/code&gt; because &lt;code&gt;Thinable&lt;/code&gt;&amp;rsquo;s that come from an &lt;code&gt;@State&lt;/code&gt; deceleration will want to work with &lt;code&gt;@Binding&lt;/code&gt; as opposed to &lt;code&gt;@Model&lt;/code&gt; objects which, since they conform to &lt;code&gt;Observation.Observable&lt;/code&gt; and are owned by the context, will be passed via &lt;code&gt;@Bindable&lt;/code&gt;. Those play very poorly together since @State provides a binding to the enclosing object and @Bindable only provides bindings to the properties. .&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Post By Me: &lt;a href=&#34;https://developer.apple.com/forums/thread/782729&#34;&gt;https://developer.apple.com/forums/thread/782729&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Post By Me: &lt;a href=&#34;https://developer.apple.com/forums/thread/783142&#34;&gt;https://developer.apple.com/forums/thread/783142&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://developer.apple.com/videos/play/wwdc2023/10149/&#34;&gt;https://developer.apple.com/videos/play/wwdc2023/10149/&lt;/a&gt; (Discover Observation in SwiftUI)&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://www.hackingwithswift.com/quick-start/swiftdata/whats-the-difference-between-bindable-and-binding&#34;&gt;https://www.hackingwithswift.com/quick-start/swiftdata/whats-the-difference-between-bindable-and-binding&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;Leaning into using SwiftData` requires different methods working with information than previous approaches. I imagine I&amp;rsquo;ll keep changing my mind as to what patterns I want to try out project by project for some time.&lt;/p&gt;
</description>
    </item>
    
    
    
    <item>
      <title>Neat, switching to the ItsyBitsy just... works</title>
      <link>https://whynotestflight.com/excuses/neat-switching-to-the-itsybitsy-just...-works/</link>
      <pubDate>Tue, 30 Apr 2024 00:00:00 +0000</pubDate>
      
      <guid>https://whynotestflight.com/excuses/neat-switching-to-the-itsybitsy-just...-works/</guid>
      <description>&lt;p&gt;Related Repo: &lt;a href=&#34;https://github.com/carlynorama/StrippedDownChipRosetta/tree/main/ARM/SAMD21G18A/01_AssemblySwitch&#34;&gt;https://github.com/carlynorama/StrippedDownChipRosetta/tree/main/ARM/SAMD21G18A/01_AssemblySwitch&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&#34;the-itsybitsy&#34;&gt;The ItsyBitsy&lt;/h2&gt;
&lt;p&gt;Switching to the ItsyBitsy from the Trinket means means I&amp;rsquo;ll able to do a breadboard circuit without worrying about smooshing the fragile little solder joints on the bottom for the programmer. (With normal Trinket usage that wouldn&amp;rsquo;t be a problem because normal sensible people use the &lt;a href=&#34;https://learn.adafruit.com/adafruit-trinket-m0-circuitpython-arduino/uf2-bootloader-details&#34;&gt;UF2 bootloader&lt;/a&gt; capabilities.)  The ItsyBitsy uses the SAMD21G18A instead of the SAMD21E18A, requiring some minor tweaks to the code. &lt;a href=&#34;https://mastodon.social/@todbot&#34;&gt;todbot&lt;/a&gt; already had one all soldered up with the headers and I snicked it.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://learn.adafruit.com/introducing-itsy-bitsy-m0&#34;&gt;https://learn.adafruit.com/introducing-itsy-bitsy-m0&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://learn.adafruit.com/introducing-itsy-bitsy-m0/downloads&#34;&gt;https://learn.adafruit.com/introducing-itsy-bitsy-m0/downloads&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://learn.adafruit.com/introducing-itsy-bitsy-m0/pinouts&#34;&gt;https://learn.adafruit.com/introducing-itsy-bitsy-m0/pinouts&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src=&#34;ItsyBitsy_pinout.png&#34; alt=&#34;Colorful pinout diagram by AdaFruit of the ItsyBitsy M0&#34;&gt;&lt;/p&gt;
&lt;h2 id=&#34;differences-between-e-and-g&#34;&gt;Differences between E and G&lt;/h2&gt;
&lt;p&gt;&lt;a href=&#34;SAMD21G18A_pinout.png&#34;&gt;Screenshot of the pinout diagram of the SAMD21G18A (5.2.1 in family datasheet)&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The G has more pins than the E. That doesn&amp;rsquo;t matter much to this project except the vector table gets two new peripherals added back in: SERCOM4, SERCOM5.  See the new startup.s [TODO LINK]&lt;/p&gt;
&lt;p&gt;To figure out what peripherals changed, I looked at the Configuration Summary (Section 2-1, page 14 in the &lt;a href=&#34;https://ww1.microchip.com/downloads/aemDocuments/documents/MCU32/ProductDocuments/DataSheets/SAM-D21-DA1-Family-Data-Sheet-DS40001882H.pdf&#34;&gt;Family Datasheet&lt;/a&gt;).&lt;/p&gt;
&lt;h2 id=&#34;making-the-circuit&#34;&gt;Making the Circuit&lt;/h2&gt;
&lt;p&gt;Unlike the &lt;a href=&#34;https://whynotestflight.com/excuses/hello-led-on-an-avr-attiny45-in-c/&#34;&gt;bare ATTiny&lt;/a&gt;, I don&amp;rsquo;t have to make the voltage regulator part of the circuit because the ItsyBitsy &lt;a href=&#34;https://learn.adafruit.com/assets/108639&#34;&gt;already has one&lt;/a&gt;. I just pulled the 3.3V and the GND into the breadboard buses. Otherwise it is pretty much the same, with extended wires out to a pseudo-header for the J-LINK.&lt;/p&gt;
&lt;p&gt;(The red and black wire up on the top right are there as another pseudo-header for providing non-USB power. I left them off the schematic )&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;switch pin: ItsyBitsy A4  / Chip PA05&lt;/li&gt;
&lt;li&gt;led pin: ItsyBitsy A3 /  Chip PA04&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src=&#34;itsy_on_breadboard.jpeg&#34; alt=&#34;Photo of the ItsyBitsy on a breadabord with an LED and momentary switch&#34;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;ItsyBitsyBasic.png&#34; alt=&#34;Schematic of ItsyBitsy with an LED and a switch.&#34;&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;ItsyBitsyBasic.kicad_sch&#34;&gt;KiCad sch File&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;itsybitsym0.kicad_sym&#34;&gt;KiCad symbol for ItsyBitsyM0&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;updating-the-code&#34;&gt;Updating the Code&lt;/h2&gt;
&lt;p&gt;Not really much to do.&lt;/p&gt;
&lt;h3 id=&#34;the-makefile&#34;&gt;The Makefile&lt;/h3&gt;
&lt;p&gt;line 7&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-make&#34; data-lang=&#34;make&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;CHIP&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;?=&lt;/span&gt; SAMD21G18A
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;startups&#34;&gt;startup.s&lt;/h3&gt;
&lt;p&gt;lines 41, 42&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-asm&#34; data-lang=&#34;asm&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#8aadf4&#34;&gt;.word&lt;/span&gt;   &lt;span style=&#34;color:#eed49f&#34;&gt;SERCOM4_Handler&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#8aadf4&#34;&gt;.word&lt;/span&gt;   &lt;span style=&#34;color:#eed49f&#34;&gt;SERCOM5_Handler&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;lines 88, 89&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-asm&#34; data-lang=&#34;asm&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;.weakref&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;SERCOM4_Handler&lt;/span&gt;, &lt;span style=&#34;color:#eed49f&#34;&gt;default_handler&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;.weakref&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;SERCOM5_Handler&lt;/span&gt;, &lt;span style=&#34;color:#eed49f&#34;&gt;default_handler&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;mains&#34;&gt;main.s&lt;/h3&gt;
&lt;h4 id=&#34;step-1&#34;&gt;step 1&lt;/h4&gt;
&lt;p&gt;lines 17, 18&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-asm&#34; data-lang=&#34;asm&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;.equ&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;ledPinOffset&lt;/span&gt;, &lt;span style=&#34;color:#f5a97f&#34;&gt;4&lt;/span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//PA04, &amp;#34;A3&amp;#34; on ItsyBitsy
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;.equ&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;switchPinOffset&lt;/span&gt;, &lt;span style=&#34;color:#f5a97f&#34;&gt;5&lt;/span&gt;  &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//PA05, &amp;#34;A4&amp;#34; on ItsyBitsy
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This works but the logic is inverted now, LED is on, unless the button is pressed, so lines 73 and 77 also need to be swapped, resulting in:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-asm&#34; data-lang=&#34;asm&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#91d7e3&#34;&gt;ledOff:&lt;/span&gt;  &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//default path
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#8aadf4&#34;&gt;STR&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;R3&lt;/span&gt;, [&lt;span style=&#34;color:#eed49f&#34;&gt;R5&lt;/span&gt;] &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//R3==ledMask, R5==portA_OUTSET
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#8aadf4&#34;&gt;B&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;loop&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#91d7e3&#34;&gt;ledOn:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#8aadf4&#34;&gt;STR&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;R3&lt;/span&gt;, [&lt;span style=&#34;color:#eed49f&#34;&gt;R6&lt;/span&gt;] &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//R3==ledMask, R6==portA_OUTCLR
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#8aadf4&#34;&gt;B&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;loop&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;and&amp;hellip; done! It works!&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;touchG_long_movto10fps.gif&#34; alt=&#34;Animated gif of the button on the circuit board being pressed.&#34;&gt;&lt;/p&gt;
&lt;h2 id=&#34;summary&#34;&gt;Summary&lt;/h2&gt;
&lt;p&gt;So these two chips come from the same family so it&amp;rsquo;s not too much of surprise the transition went smoothly. The real test of the Arm promise will be sharing code between one of these M0+ and a chip with a different Coretex-M rating. To do that it would make sense to be working up in the C so the compiler can handle rendering the different appropriate assembly code. A mixed C/Assembly project&amp;rsquo;s the next step!&lt;/p&gt;
</description>
    </item>
    
    
    
    <item>
      <title>It&#39;d make sense to do some toolchain clean up</title>
      <link>https://whynotestflight.com/excuses/itd-make-sense-to-do-some-toolchain-clean-up/</link>
      <pubDate>Sat, 27 Apr 2024 00:00:00 +0000</pubDate>
      
      <guid>https://whynotestflight.com/excuses/itd-make-sense-to-do-some-toolchain-clean-up/</guid>
      <description>&lt;p&gt;My Makefile was a bit of a &amp;ldquo;get it done&amp;rdquo; hack. It still will be after this session, but a better one!&lt;/p&gt;
&lt;h3 id=&#34;goals&#34;&gt;Goals&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;clean up how makefile finds its sources in prep for switching chips&lt;/li&gt;
&lt;li&gt;clean up assembler options for .s vs .S&lt;/li&gt;
&lt;li&gt;break apart OpenOCD tasks&lt;/li&gt;
&lt;li&gt;make launching GDB easier&lt;/li&gt;
&lt;li&gt;automate some of the gdb tasks&lt;/li&gt;
&lt;li&gt;add the .PHONY&lt;/li&gt;
&lt;li&gt;clean up the comments (make headers, trailing whitespace matters)&lt;/li&gt;
&lt;li&gt;small misc improvements&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Related Repo: &lt;a href=&#34;https://github.com/carlynorama/StrippedDownChipRosetta/tree/main/ARM/SAMD21E18/05_Structure&#34;&gt;https://github.com/carlynorama/StrippedDownChipRosetta/tree/main/ARM/SAMD21E18/05_Structure&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&#34;conditional-find-files&#34;&gt;Conditional Find Files&lt;/h2&gt;
&lt;p&gt;I&amp;rsquo;m going to switch from the SAMD21E18A to the SAMD21G18A the next post because &lt;a href=&#34;https://mastodon.social/@todbot/&#34;&gt;todbot&lt;/a&gt; has an &lt;a href=&#34;https://www.adafruit.com/product/3727&#34;&gt;ItsyBitsy M0 Express&lt;/a&gt; ready to swipe and it&amp;rsquo;s bugging me that the LED and the switch don&amp;rsquo;t match the AVR example.&lt;/p&gt;
&lt;p&gt;This means my code may end up being able to support &lt;em&gt;two&lt;/em&gt; chips if I get fancy with my Makefile. To start, proof of concept with the original files.&lt;/p&gt;
&lt;h3 id=&#34;new-directory-layout&#34;&gt;New directory layout&lt;/h3&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;└── Project
    └── SAMD21E18A
    │   └── linker.ld
    |   └── startup.s 
    └── main.s
    └── Makefile
&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=&#34;new-additions-to-the-makefile&#34;&gt;New additions to the Makefile&lt;/h3&gt;
&lt;p&gt;I had switched to hard coding the files when I split into main.s and startup.s, now it&amp;rsquo;s time to switch back to a more automated search.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-make&#34; data-lang=&#34;make&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;CHIP&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;?=&lt;/span&gt; SAMD21E18A
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;MCU&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;:=&lt;/span&gt; cortex-m0plus
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;LINKER_FILE&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;?=&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;$(&lt;/span&gt;CHIP&lt;span style=&#34;color:#c6a0f6&#34;&gt;)&lt;/span&gt;/linker.ld
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;SOURCES&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;$(&lt;/span&gt;wildcard *.s&lt;span style=&#34;color:#c6a0f6&#34;&gt;)&lt;/span&gt; &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# only this dir&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;SOURCES&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;+=&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;$(&lt;/span&gt;wildcard *.S&lt;span style=&#34;color:#c6a0f6&#34;&gt;)&lt;/span&gt; &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# only this dir&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;SOURCES&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;+=&lt;/span&gt; startup.s &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# all dir in VPATH&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;VPATH&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;$(&lt;/span&gt;CHIP&lt;span style=&#34;color:#c6a0f6&#34;&gt;)&lt;/span&gt; &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#will look in this folder for missing files in sources.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;OBJECTS&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;$(&lt;/span&gt;addsuffix .o, &lt;span style=&#34;color:#c6a0f6&#34;&gt;$(&lt;/span&gt;basename &lt;span style=&#34;color:#c6a0f6&#34;&gt;$(&lt;/span&gt;SOURCES&lt;span style=&#34;color:#c6a0f6&#34;&gt;)))&lt;/span&gt; &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#replaces any suffix&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This portion sets up the Makefile to look both in the current directory and anywhere added to the &lt;code&gt;VPATH&lt;/code&gt; for the files it needs later on.  &lt;code&gt;VPATH&lt;/code&gt; is a built in variable. The new custom variable &lt;code&gt;CHIP&lt;/code&gt; sets the string indicating which SAMD21 chip is currently on deck. The string gets added to the &lt;code&gt;VPATH&lt;/code&gt; as a directory name.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Note: The linker script called with the -T flag needs its full path. To see the default linker script that would be used without that flag add &lt;code&gt;-Wl,--verbose&lt;/code&gt; to the linker flags.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Note: to get arm-gcc to spit out the list of mcpu options use &lt;code&gt;arm-none-eabi-gcc --target-help -mcpu=nonsense&lt;/code&gt; where &amp;ldquo;nonsense&amp;rdquo; can be anything invalid. from &lt;a href=&#34;https://stackoverflow.com/questions/53156919/what-are-my-available-march-mtune-options&#34;&gt;stackoverflow&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Longer aside:&lt;/strong&gt; I&amp;rsquo;ve been switching between &lt;code&gt;:=&lt;/code&gt;, &lt;code&gt;=&lt;/code&gt; and &lt;code&gt;=?&lt;/code&gt; for my assignments. Simplistically&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;:=&lt;/code&gt;: &amp;ldquo;calculate this here, this is final&amp;rdquo;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;=&lt;/code&gt; : &amp;ldquo;store the calculation and run it at every call site&amp;rdquo;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;=?&lt;/code&gt; : &amp;ldquo;if there isn&amp;rsquo;t an environment variable, use this&amp;rdquo;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;code&gt;::=&lt;/code&gt; and &lt;code&gt;:::=&lt;/code&gt; are &lt;a href=&#34;https://www.gnu.org/software/make/manual/html_node/Setting.html&#34;&gt;assignment operators too&lt;/a&gt;. (More precisely &lt;code&gt;:=&lt;/code&gt; assigns &amp;ldquo;&lt;a href=&#34;https://www.gnu.org/software/make/manual/html_node/Simple-Assignment.html&#34;&gt;simply expanded variables&lt;/a&gt;&amp;rdquo; and = assigns &amp;ldquo;&lt;a href=&#34;https://www.gnu.org/software/make/manual/html_node/Recursive-Assignment.html&#34;&gt;recursively expanded&lt;/a&gt;&amp;rdquo; variables, see the list of &lt;a href=&#34;https://www.gnu.org/software/make/manual/html_node/Flavors.html&#34;&gt;variable flavors&lt;/a&gt;)&lt;/p&gt;
&lt;h2 id=&#34;sorting-out-s-vs-s&#34;&gt;Sorting out .s vs .S&lt;/h2&gt;
&lt;p&gt;If you&amp;rsquo;ve never already, go to a working directory without a makefile in it and type &lt;code&gt;make -p&lt;/code&gt; to see all the implicit variables and commands &lt;code&gt;make&lt;/code&gt; uses under the hood.&lt;/p&gt;
&lt;p&gt;In many setups, adding steps like &lt;code&gt;%.o:%.s&lt;/code&gt; or &lt;code&gt;%.o:%.S&lt;/code&gt; or &lt;code&gt;%.o:%.c&lt;/code&gt; isn&amp;rsquo;t needed because &lt;code&gt;make&lt;/code&gt; already has sensible defaults for &amp;ldquo;transform every x file into needed y file&amp;rdquo;&lt;/p&gt;
&lt;p&gt;Also, in many setups the assembler will never see human written pure assembly files. All pure assembly will have been written by the compiler.&lt;/p&gt;
&lt;p&gt;What&amp;rsquo;s the general difference between the &lt;code&gt;.S&lt;/code&gt; and &lt;code&gt;.s&lt;/code&gt; suffix? Well, we can see in the default rules that:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;.s&lt;/code&gt; files are expected to be ready as is to be made into an object&lt;/li&gt;
&lt;li&gt;&lt;code&gt;.S&lt;/code&gt; files get extra preprocessing.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;# default
PREPROCESS.S = $(CC) -E $(CPPFLAGS)

# default
COMPILE.S = $(CC) $(ASFLAGS) $(CPPFLAGS) $(TARGET_MACH) -c

# default
LINK.S = $(CC) $(ASFLAGS) $(CPPFLAGS) $(LDFLAGS) $(TARGET_MACH)

# default
COMPILE.s = $(AS) $(ASFLAGS) $(TARGET_MACH)

# default
LINK.s = $(CC) $(ASFLAGS) $(LDFLAGS) $(TARGET_MACH)

%: %.s
#  commands to execute (built-in):
	$(LINK.s) $^ $(LOADLIBES) $(LDLIBS) -o $@

%.o: %.s
#  commands to execute (built-in):
	$(COMPILE.s) -o $@ $&amp;lt;

%: %.S
#  commands to execute (built-in):
	$(LINK.S) $^ $(LOADLIBES) $(LDLIBS) -o $@

%.o: %.S
#  commands to execute (built-in):
	$(COMPILE.S) -o $@ $&amp;lt;

%.s: %.S
#  commands to execute (built-in):
	$(PREPROCESS.S) $&amp;lt; &amp;gt; $@
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;S files &amp;ldquo;might include C preprocessing statements (#define, #ifdef, and etc.), but they should not contain C statements&amp;rdquo; (microchip online docs: brief &lt;a href=&#34;https://onlinedocs.microchip.com/pr/GUID-C4E60FF5-3DAB-44F1-BA61-4BD962D8F469-en-US-2/index.html?GUID-355BD84C-B279-485D-90C3-35E66AAFD4C6&#34;&gt;FAQ answer&lt;/a&gt; , &lt;a href=&#34;https://onlinedocs.microchip.com/pr/GUID-C4E60FF5-3DAB-44F1-BA61-4BD962D8F469-en-US-2/index.html?GUID-59C518BE-10D0-4B11-95A4-4C1401F1F1DA&#34;&gt;output files list&lt;/a&gt;)&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ve been personally sloppy on whether my hand rolled assembly should get the .s or .S suffix because of all the .___ compiler directives (&lt;code&gt;.thumb&lt;/code&gt;, &lt;code&gt;.syntax unified&lt;/code&gt;)  and C style comments in them threw me for a loop.  In a related sloppiness, I&amp;rsquo;ve been using the &lt;code&gt;-x assembler-with-cpp&lt;/code&gt; option without questioning it for the .s files, even though they shouldn&amp;rsquo;t need it.&lt;/p&gt;
&lt;p&gt;Back when working on &lt;a href=&#34;https://github.com/carlynorama/StrippedDownChipRosetta/blob/main/ARM/SAMD21E18/02_AssemblyStartUp/README.md&#34;&gt;separating the startup file&lt;/a&gt;, I did confirm the actual assembler works just fine with this flavor of assembly, so I&amp;rsquo;m going to get a little less sloppy and use the assembler for .s and the complier with &lt;code&gt;-x assembler-with-cpp&lt;/code&gt; for .S files.&lt;/p&gt;
&lt;p&gt;My main tool variables and build rules now look like&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-make&#34; data-lang=&#34;make&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;TOOL_BASE&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;:=&lt;/span&gt; arm-none-eabi-
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;CC&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;$(&lt;/span&gt;TOOL_BASE&lt;span style=&#34;color:#c6a0f6&#34;&gt;)&lt;/span&gt;gcc
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;AS&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;$(&lt;/span&gt;TOOL_BASE&lt;span style=&#34;color:#c6a0f6&#34;&gt;)&lt;/span&gt;as
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-make&#34; data-lang=&#34;make&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## Default
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;all&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;$(&lt;/span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;OBJECTS&lt;/span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;)&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;$(&lt;/span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;TARGET&lt;/span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;)&lt;/span&gt;.elf
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## Assembler
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;%.o&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;:&lt;/span&gt;%.s
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	&lt;span style=&#34;color:#c6a0f6&#34;&gt;$(&lt;/span&gt;AS&lt;span style=&#34;color:#c6a0f6&#34;&gt;)&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;$(&lt;/span&gt;ASFLAGS&lt;span style=&#34;color:#c6a0f6&#34;&gt;)&lt;/span&gt; -c $&amp;lt; -o &lt;span style=&#34;color:#f4dbd6&#34;&gt;$@&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;%.o&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;:&lt;/span&gt;%.S
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	&lt;span style=&#34;color:#c6a0f6&#34;&gt;$(&lt;/span&gt;CC&lt;span style=&#34;color:#c6a0f6&#34;&gt;)&lt;/span&gt; -x assembler-with-cpp -c &lt;span style=&#34;color:#c6a0f6&#34;&gt;$(&lt;/span&gt;CFLAGS&lt;span style=&#34;color:#c6a0f6&#34;&gt;)&lt;/span&gt; $&amp;lt; &amp;gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;$@&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## Linker
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;$(TARGET).elf&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;$(&lt;/span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;OBJECTS&lt;/span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	 &lt;span style=&#34;color:#c6a0f6&#34;&gt;$(&lt;/span&gt;CC&lt;span style=&#34;color:#c6a0f6&#34;&gt;)&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;$(&lt;/span&gt;LDFLAGS&lt;span style=&#34;color:#c6a0f6&#34;&gt;)&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;$(&lt;/span&gt;OBJECTS&lt;span style=&#34;color:#c6a0f6&#34;&gt;)&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;$(&lt;/span&gt;LINKONLYOBJECTS&lt;span style=&#34;color:#c6a0f6&#34;&gt;)&lt;/span&gt;  -T./&lt;span style=&#34;color:#c6a0f6&#34;&gt;$(&lt;/span&gt;LINKER_FILE&lt;span style=&#34;color:#c6a0f6&#34;&gt;)&lt;/span&gt; -o &lt;span style=&#34;color:#f4dbd6&#34;&gt;$@&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;improving-openocd-shortcuts&#34;&gt;Improving OpenOCD shortcuts&lt;/h2&gt;
&lt;p&gt;OpenOCD can be &lt;a href=&#34;https://github.com/espressif/openocd-esp32/blob/8133bce9617610279a1a1988a6921882610a7409/tcl/target/esp_common.cfg&#34;&gt;way way fancier&lt;/a&gt; than anything I&amp;rsquo;m doing, but I&amp;rsquo;ve tired to modularize the project a bit.  The previous Makefile only had the one &amp;ldquo;load-program and launch servers&amp;rdquo; command. I&amp;rsquo;ve made some more rules and pushed the asscoiated files into their own directory. I&amp;rsquo;ve tried to show both stowing options in files and calling commands directly from the Makefile.&lt;/p&gt;
&lt;h3 id=&#34;new-files&#34;&gt;New Files&lt;/h3&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;└── Project
    └── openocd
    │   └── segger.cfg
    |   └── SAMD21E18A.cfg 
    |   └── flash_program_prep.cfg 
    └── SAMD21E18A
    │   └── linker.ld
    |   └── startup.s 
    └── main.s
    └── Makefile
&lt;/code&gt;&lt;/pre&gt;&lt;h4 id=&#34;seggercfg&#34;&gt;segger.cfg&lt;/h4&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-cfg&#34; data-lang=&#34;cfg&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# Segger J-Link EDU, SWD modere&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;adapter driver jlink&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;transport select swd&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h4 id=&#34;samd21e18acfg&#34;&gt;SAMD21E18A.cfg&lt;/h4&gt;
&lt;p&gt;same name as used for $(CHIP)&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-cfg&#34; data-lang=&#34;cfg&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;set CHIPNAME at91samd21e18&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;source [find target/at91samdXX.cfg]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h4 id=&#34;flash_program_prepcfg&#34;&gt;flash_program_prep.cfg&lt;/h4&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-cfg&#34; data-lang=&#34;cfg&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;init&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;reset halt&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;at91samd bootloader 0  #clear bootloader &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;new-variables&#34;&gt;New variables&lt;/h3&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-make&#34; data-lang=&#34;make&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;PROGRAMMER&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;:=&lt;/span&gt; openocd
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;PRGMR_FILES_DIR&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;:=&lt;/span&gt; openocd/
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;PROGRAMMER_COMMON&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; -f &lt;span style=&#34;color:#c6a0f6&#34;&gt;$(&lt;/span&gt;PRGMR_FILES_DIR&lt;span style=&#34;color:#c6a0f6&#34;&gt;)&lt;/span&gt;segger.cfg  &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#load hardware&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;PROGRAMMER_COMMON&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;+=&lt;/span&gt; -f &lt;span style=&#34;color:#c6a0f6&#34;&gt;$(&lt;/span&gt;PRGMR_FILES_DIR&lt;span style=&#34;color:#c6a0f6&#34;&gt;)$(&lt;/span&gt;CHIP&lt;span style=&#34;color:#c6a0f6&#34;&gt;)&lt;/span&gt;.cfg &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#load chip description&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;FLASH_FLAGS&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;$(&lt;/span&gt;PROGRAMMER_COMMON&lt;span style=&#34;color:#c6a0f6&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;FLASH_FLAGS&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;+=&lt;/span&gt; -f &lt;span style=&#34;color:#c6a0f6&#34;&gt;$(&lt;/span&gt;PRGMR_FILES_DIR&lt;span style=&#34;color:#c6a0f6&#34;&gt;)&lt;/span&gt;flash_program_prep.cfg
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;FLASH_FLAGS&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;+=&lt;/span&gt; -c &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;program &lt;/span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;$(&lt;/span&gt;TARGET&lt;span style=&#34;color:#c6a0f6&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;.elf verify reset exit&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;new-rules&#34;&gt;New rules&lt;/h3&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-make&#34; data-lang=&#34;make&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# Program the device.  
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;flash&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;$(&lt;/span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;TARGET&lt;/span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;)&lt;/span&gt;.elf
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	&lt;span style=&#34;color:#c6a0f6&#34;&gt;$(&lt;/span&gt;PROGRAMMER&lt;span style=&#34;color:#c6a0f6&#34;&gt;)&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;$(&lt;/span&gt;FLASH_FLAGS&lt;span style=&#34;color:#c6a0f6&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#fns == &amp;#34;flash and serve&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;fns&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;$(&lt;/span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;TARGET&lt;/span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;)&lt;/span&gt;.elf
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	&lt;span style=&#34;color:#c6a0f6&#34;&gt;$(&lt;/span&gt;PROGRAMMER&lt;span style=&#34;color:#c6a0f6&#34;&gt;)&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;$(&lt;/span&gt;PROGRAMMER_COMMON&lt;span style=&#34;color:#c6a0f6&#34;&gt;)&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;&lt;/span&gt;	-f &lt;span style=&#34;color:#c6a0f6&#34;&gt;$(&lt;/span&gt;PRGMR_FILES_DIR&lt;span style=&#34;color:#c6a0f6&#34;&gt;)&lt;/span&gt;flash_program_prep.cfg &lt;span style=&#34;color:#8aadf4&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;&lt;/span&gt;	-c &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;program &lt;/span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;$(&lt;/span&gt;TARGET&lt;span style=&#34;color:#c6a0f6&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;.elf verify&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;serve&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	&lt;span style=&#34;color:#c6a0f6&#34;&gt;$(&lt;/span&gt;PROGRAMMER&lt;span style=&#34;color:#c6a0f6&#34;&gt;)&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;$(&lt;/span&gt;PROGRAMMER_COMMON&lt;span style=&#34;color:#c6a0f6&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;talk&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;:&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	telnet localhost &lt;span style=&#34;color:#f5a97f&#34;&gt;4444&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;.PHONY&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;:&lt;/span&gt; talk serve
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;improving-gdb-shortcuts&#34;&gt;Improving GDB shortcuts&lt;/h2&gt;
&lt;p&gt;Like with OpenOCD, GDB encompasses huge capabilities, which I&amp;rsquo;m only lightly touching on. Again, did some modularization and some convenience instructions. Again trying to show performing some tasks inline in the Makefile and others in external files.&lt;/p&gt;
&lt;p&gt;GDB has a whole auto-loading schema of rules and extensions that I&amp;rsquo;m not touching AT ALL, but I&amp;rsquo;ve put some links in the references.&lt;/p&gt;
&lt;h3 id=&#34;new-files-1&#34;&gt;New Files&lt;/h3&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;└── Project
    └── gdb
    │   └── main_breakpoints.txt
    |   └── mem_locs.txt  
    └── openocd
    │   └── segger.cfg
    |   └── SAMD21E18A.cfg 
    |   └── flash_program_prep.cfg 
    └── SAMD21E18A
    │   └── linker.ld
    |   └── startup.s 
    └── main.s
    └── Makefile
&lt;/code&gt;&lt;/pre&gt;&lt;h4 id=&#34;main_breakpointstxt&#34;&gt;main_breakpoints.txt&lt;/h4&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;break loop
break _start
break multiPinPullup
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;One way to generate this file would be to quickly add all functions with &lt;code&gt;rbreak .&lt;/code&gt; and &lt;code&gt;del [break point number]&lt;/code&gt; or &lt;code&gt;clear [filename:linenum]&lt;/code&gt; unwanted ones (see current with &lt;code&gt;info break&lt;/code&gt; or just &lt;code&gt;i b&lt;/code&gt;). Once the breakpoints look the way that works use &lt;code&gt;save breakpoints [filename]&lt;/code&gt; to generate the file.&lt;/p&gt;
&lt;p&gt;For an example usage see the new Makefile rule below.&lt;/p&gt;
&lt;h4 id=&#34;mem_locstxt&#34;&gt;mem_locs.txt&lt;/h4&gt;
&lt;p&gt;Comments on own line only.&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;# for the direction set
x/1x 0x41004400 
# for the current output values
x/1x 0x41004410
# for the PINCFG settings, PA07 is top
x/1x 0x41004444 
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Example usage, witch gdb session open try &lt;code&gt;source gdb/mem_locs.txt&lt;/code&gt; and the responses should load.&lt;/p&gt;
&lt;h3 id=&#34;tool-def--variables&#34;&gt;Tool Def &amp;amp; Variables&lt;/h3&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;DEBUGGER = $(TOOL_BASE)gdb
&lt;/code&gt;&lt;/pre&gt;&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;DEBUGGER_FILES_DIR = gdb/
DEBUG_FLAGS = -iex &amp;#34;target extended-remote localhost:3333&amp;#34;
DEBUG_FLAGS += -ex &amp;#34;layout regs&amp;#34;
DEBUG_FLAGS += -ex &amp;#34;source $(DEBUGGER_FILES_DIR)main_breakpoints.txt&amp;#34;
&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=&#34;new-rule&#34;&gt;New Rule&lt;/h3&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-make&#34; data-lang=&#34;make&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;debug&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;$(&lt;/span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;TARGET&lt;/span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;)&lt;/span&gt;.elf
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	&lt;span style=&#34;color:#c6a0f6&#34;&gt;$(&lt;/span&gt;DEBUGGER&lt;span style=&#34;color:#c6a0f6&#34;&gt;)&lt;/span&gt; $^ &lt;span style=&#34;color:#c6a0f6&#34;&gt;$(&lt;/span&gt;DEBUG_FLAGS&lt;span style=&#34;color:#c6a0f6&#34;&gt;)&lt;/span&gt; &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#$^ inserts ALL the listed input files. &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;adding-in-phony&#34;&gt;Adding in PHONY&lt;/h2&gt;
&lt;p&gt;&lt;a href=&#34;https://www.gnu.org/software/make/manual/html_node/Phony-Targets.html&#34;&gt;&lt;code&gt;.PHONY&lt;/code&gt;&lt;/a&gt; chiefly protect against a rule/file name collision preventing a rule from running. I hadn&amp;rsquo;t been having that trouble, but it&amp;rsquo;s the right thing to do. (There are other more specific reasons to use it, read the linked doc)&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;## Phony List 
.PHONY: all talk debug res_check clean serve fnl flash symb disamb symb_o disamb_o
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&#34;helpful-references&#34;&gt;Helpful References&lt;/h2&gt;
&lt;h3 id=&#34;makefiles&#34;&gt;Makefiles&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://www.gnu.org/software/make/manual/html_node/Makefile-Basics.html&#34;&gt;https://www.gnu.org/software/make/manual/html_node/Makefile-Basics.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://www.gnu.org/software/make/manual/html_node/Using-Variables.html&#34;&gt;https://www.gnu.org/software/make/manual/html_node/Using-Variables.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://www.gnu.org/software/make/manual/html_node/Automatic-Variables.html&#34;&gt;https://www.gnu.org/software/make/manual/html_node/Automatic-Variables.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://www.gnu.org/software/make/manual/html_node/Flavors.html&#34;&gt;https://www.gnu.org/software/make/manual/html_node/Flavors.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://www.gnu.org/software/make/manual/html_node/Catalogue-of-Rules.html&#34;&gt;https://www.gnu.org/software/make/manual/html_node/Catalogue-of-Rules.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://www.gnu.org/software/make/manual/html_node/Implicit-Rules.html&#34;&gt;https://www.gnu.org/software/make/manual/html_node/Implicit-Rules.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://www.gnu.org/software/make/manual/html_node/Pattern-Rules.html&#34;&gt;https://www.gnu.org/software/make/manual/html_node/Pattern-Rules.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://www.gnu.org/software/make/manual/html_node/Phony-Targets.html&#34;&gt;https://www.gnu.org/software/make/manual/html_node/Phony-Targets.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://make.mad-scientist.net/papers/rules-of-makefiles/&#34;&gt;https://make.mad-scientist.net/papers/rules-of-makefiles/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://make.mad-scientist.net/papers/how-not-to-use-vpath/&#34;&gt;https://make.mad-scientist.net/papers/how-not-to-use-vpath/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://whynotestflight.com/tags/makefile/&#34;&gt;Makefile tag&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;gcc--as&#34;&gt;gcc &amp;amp; as&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://sourceware.org/binutils/docs-2.42/as/Invoking.html&#34;&gt;https://sourceware.org/binutils/docs-2.42/as/Invoking.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://gcc.gnu.org/onlinedocs/gcc/Option-Summary.html&#34;&gt;https://gcc.gnu.org/onlinedocs/gcc/Option-Summary.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://gcc.gnu.org/onlinedocs/gcc/ARM-Options.html&#34;&gt;https://gcc.gnu.org/onlinedocs/gcc/ARM-Options.html&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;gdb&#34;&gt;GDB&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://sourceware.org/gdb/current/onlinedocs/gdb.html/Breakpoints.html&#34;&gt;https://sourceware.org/gdb/current/onlinedocs/gdb.html/Breakpoints.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://sourceware.org/gdb/current/onlinedocs/gdb.html/Save-Breakpoints.html&#34;&gt;https://sourceware.org/gdb/current/onlinedocs/gdb.html/Save-Breakpoints.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://sourceware.org/gdb/current/onlinedocs/gdb.html/Command-Files.html&#34;&gt;https://sourceware.org/gdb/current/onlinedocs/gdb.html/Command-Files.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://sourceware.org/gdb/current/onlinedocs/gdb.html/Extending-GDB.html&#34;&gt;https://sourceware.org/gdb/current/onlinedocs/gdb.html/Extending-GDB.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://sourceware.org/gdb/current/onlinedocs/gdb.html/Sequences.html&#34;&gt;https://sourceware.org/gdb/current/onlinedocs/gdb.html/Sequences.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;example gdbinit file: &lt;a href=&#34;https://gist.github.com/CocoaBeans/1879270&#34;&gt;https://gist.github.com/CocoaBeans/1879270&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;example &lt;a href=&#34;https://github.com/pytorch/pytorch/blob/36af9c0d7da5159a94cd1c9e2204aeeb1ca13c56/.gdbinit&#34;&gt;gdbinit&lt;/a&gt; file that loads an &lt;a href=&#34;https://github.com/pytorch/pytorch/blob/83e7b9d25fd33cff129107738ea280806dd23db3/tools/gdb/pytorch-gdb.py&#34;&gt;extension written in python&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;summary&#34;&gt;Summary&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;input checked=&#34;&#34; disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; clean up how makefile finds its sources in prep for switching chips&lt;/li&gt;
&lt;li&gt;&lt;input checked=&#34;&#34; disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; clean up assembler options for .s vs .S&lt;/li&gt;
&lt;li&gt;&lt;input checked=&#34;&#34; disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; break apart openocd tasks&lt;/li&gt;
&lt;li&gt;&lt;input checked=&#34;&#34; disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; make launching gdb easier&lt;/li&gt;
&lt;li&gt;&lt;input checked=&#34;&#34; disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; automate some of the gdb tasks&lt;/li&gt;
&lt;li&gt;&lt;input checked=&#34;&#34; disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; add the .PHONY&lt;/li&gt;
&lt;li&gt;&lt;input checked=&#34;&#34; disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; clean up the comments (make headers, trailing whitespace matters)&lt;/li&gt;
&lt;li&gt;&lt;input checked=&#34;&#34; disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; small misc improvements&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Next to update the actual circuit!&lt;/p&gt;
&lt;h2 id=&#34;full-makefile&#34;&gt;Full Makefile&lt;/h2&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;###############################################################################
# Makefile for a simple SAMD21 Assembly project
###############################################################################

TARGET ?= combined

CHIP ?= SAMD21E18A
MCU := cortex-m0plus

###############################################################################
## Resoruces
LINKER_FILE ?= $(CHIP)/linker.ld

SOURCES = $(wildcard *.s)# only this dir
SOURCES += $(wildcard *.S)# only this dir
SOURCES += startup.s# all dir in VPATH

VPATH=$(CHIP)#will look in this folder for missing files in sources.

OBJECTS = $(addsuffix .o, $(basename $(SOURCES)))#replaces any suffix

###############################################################################
## Tools
TOOL_BASE := arm-none-eabi-
CC := $(TOOL_BASE)gcc
AS := $(TOOL_BASE)as
OBJD := $(TOOL_BASE)objdump
DEBUGGER := $(TOOL_BASE)gdb
NM := $(TOOL_BASE)nm

PROGRAMMER := openocd

###############################################################################
## Flags

## Options common to compile, link and assembly rules
COMMON = -mcpu=$(MCU)
COMMON += -mthumb

## Compile options common for all C compilation units.
CFLAGS = $(COMMON)
CFLAGS += -Wall
CFLAGS += -g
#CFLAGS += -Os #compression

ASFLAGS = $(CFLAGS)

## Linker flags
LDFLAGS = $(COMMON)
LDFLAGS += --specs=nosys.specs -nostdlib -lgcc
LDFLAGS += -Wl,-Map=$(TARGET).map

# Programming &amp;amp; Debugging 
PRGMR_FILES_DIR = openocd/
PROGRAMMER_COMMON = -f $(PRGMR_FILES_DIR)segger.cfg#load hardware
PROGRAMMER_COMMON += -f $(PRGMR_FILES_DIR)$(CHIP).cfg#load chip description

FLASH_FLAGS = $(PROGRAMMER_COMMON)
FLASH_FLAGS += -f $(PRGMR_FILES_DIR)flash_program_prep.cfg
FLASH_FLAGS += -c &amp;#34;program $(TARGET).elf verify reset exit&amp;#34;

DEBUGGER_FILES_DIR = gdb/
DEBUG_FLAGS = -iex &amp;#34;target extended-remote localhost:3333&amp;#34;
DEBUG_FLAGS += -ex &amp;#34;layout regs&amp;#34;
DEBUG_FLAGS += -ex &amp;#34;source $(DEBUGGER_FILES_DIR)main_breakpoints.txt&amp;#34;

###############################################################################
## Rules

all: $(OBJECTS) $(TARGET).elf

## Assembler
%.o:%.s
	$(AS) $(ASFLAGS) $&amp;lt; -o $@

%.o:%.S
	$(CC) -x assembler-with-cpp -c $(CFLAGS) $&amp;lt; &amp;gt;$@

## Linker
$(TARGET).elf: $(OBJECTS)
	 $(CC) $(LDFLAGS) $(OBJECTS) $(LINKONLYOBJECTS)  -T./$(LINKER_FILE) -o $@
	
## Simple Checking 
%.lss: $(TARGET).elf
	$(OBJD) -h -S $&amp;lt; &amp;gt;$@

disamb: $(TARGET).elf
	$(OBJD) --disassemble $&amp;lt;

disamb_o: $(OBJECTS)
	$(OBJD) --disassemble $^

symb: $(TARGET).elf
	$(NM) --numeric-sort $&amp;lt;

symb_o: $(OBJECTS)
	$(NM) --numeric-sort $^

## Programming &amp;amp; Debugging  
flash: $(TARGET).elf
	$(PROGRAMMER) $(FLASH_FLAGS)


fnl: $(TARGET).elf
	$(PROGRAMMER) $(PROGRAMMER_COMMON) \
	-f $(PRGMR_FILES_DIR)flash_program_prep.cfg \
	-c &amp;#34;program $(TARGET).elf verify&amp;#34;

serve:
	$(PROGRAMMER) $(PROGRAMMER_COMMON)

talk: 
	telnet localhost 4444

debug: $(TARGET).elf
	$(DEBUGGER) $(TARGET).elf $(DEBUG_FLAGS)

## Utilities
clean:
	-rm -rf $(OBJECTS) $(TARGET).elf $(TARGET).map

# &amp;#34;resource check&amp;#34; - to get list of items make expects to find
res_check:
	@echo $(SOURCES)
	@echo $(OBJECTS)

## Phony List 
.PHONY: all talk debug res_check clean serve fnl flash symb disamb symb_o disamb_o
&lt;/code&gt;&lt;/pre&gt;</description>
    </item>
    
    
    
    <item>
      <title>And now for 3 ways to set an internal pullup</title>
      <link>https://whynotestflight.com/excuses/and-now-for-3-ways-to-set-an-internal-pullup/</link>
      <pubDate>Tue, 23 Apr 2024 00:00:00 +0000</pubDate>
      
      <guid>https://whynotestflight.com/excuses/and-now-for-3-ways-to-set-an-internal-pullup/</guid>
      <description>&lt;style&gt;
table.foo2 {
    margin-top:1em;
    padding:0px;
    line-height:1.2em;
    font-size:smaller;
    font-family:Arial, Verdana, Tahoma, Helvetica, sans-serif;
    text-decoration:none;
    white-space:pre-wrap;
    min-width:80%;
}
table.foo2 td {
  margin: 5px;
  
}

table.foo2 th {
    font-family:Arial, Verdana, Tahoma, Helvetica, sans-serif;
    font-weight:200;
}

table.foo2 strong {
  font-weight:1200;
}

.take_away {
    color: #88AAEE;
}

.data {
    font-size:smaller;
}

h4.take_away {
    margin-bottom: 5px 
}

.odd td:nth-child(odd)  {
  /*border: 2px solid orange; */
   color: #88AAEE;
  margin-bottom: 1px;
}

table.odd {
    font-size:smaller;
}
&lt;/style&gt;
&lt;ul&gt;
&lt;li&gt;Related Repo: &lt;a href=&#34;https://github.com/carlynorama/StrippedDownChipRosetta/blob/main/ARM/SAMD21E18/04_AssemblySwtich/&#34;&gt;https://github.com/carlynorama/StrippedDownChipRosetta/blob/main/ARM/SAMD21E18/04_AssemblySwtich/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Slowly working towards parity with the &lt;a href=&#34;https://whynotestflight.com/excuses/hello-led-on-an-avr-attiny45-in-c/&#34;&gt;AVR example&lt;/a&gt;, this post adds the switch with an internal pullup resistor.  One of the nice things about internal pullups? The part of a switch can comfortably be played by some 22 AWG yellow wire from the Dish of Scrap Miscellany.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;touch_320.gif&#34; alt=&#34;Animated GIF of the LED being switched on and off&#34;&gt;&lt;/p&gt;
&lt;h2 id=&#34;circuit-warning&#34;&gt;Circuit Warning&lt;/h2&gt;
&lt;p&gt;This circuit doesn&amp;rsquo;t match the &lt;a href=&#34;https://whynotestflight.com/excuses/hello-led-on-an-avr-attiny45-in-c/&#34;&gt;AVR circuit&lt;/a&gt;. The AVR Circuit sank the LED and pulled up the switch, following classic recommend practice. This circuit:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;different:&lt;/strong&gt; sources the LED, because that&amp;rsquo;s the Arduino built-in LED convention. (Off==On is kinda hard for intro classes)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;same:&lt;/strong&gt; pulls up the switch&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Since the switch and led don&amp;rsquo;t match electrically, the code will handle the inversion to get the same result as the AVR circuit. (On when closed, off when open)&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;trinket_1_switch.svg&#34; alt=&#34;circuit diagram of LED and switch hooked up to trinket. LED is the built in LED (PA10) and the switch is hooked up to D3 (PA07) and GND&#34;&gt;&lt;/p&gt;
&lt;h2 id=&#34;bit-hacking&#34;&gt;&amp;ldquo;Bit Hacking&amp;rdquo;&lt;/h2&gt;
&lt;p&gt;Checking a switch and conditionally turning on an LED requires some fancier moves than setting an LED alone.  I made an &lt;a href=&#34;https://cpulator.01xz.net/?sys=arm-de1soc&amp;amp;d_audio=48000&amp;amp;loadasm=share/skLx63e.s&#34;&gt;emulator script&lt;/a&gt; with some examples. The two-step instructions like &lt;code&gt;MOV R1, R0, LSL #6&lt;/code&gt; need to be broken up and &lt;code&gt;MOV&lt;/code&gt; changed to &lt;code&gt;MOVS&lt;/code&gt; on the actual chip (&lt;code&gt;MOV&lt;/code&gt; is reserved for specific registers on CM0+), but the concepts translate.&lt;/p&gt;
&lt;h3 id=&#34;references&#34;&gt;References&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;
    
        
            
    YouTube:
    &lt;a href=&#34;https://www.youtube.com/watch?v=ZusiKXcz_ac&amp;amp;list=PLUl4u3cNGP63VIBQVWguXxZZi0566y7Wf&#34;&gt;3: Bit Hacks&lt;/a&gt;
             (8:22) as part of
            &lt;a href=&#34;https://www.youtube.com/playlist?list=PLUl4u3cNGP63VIBQVWguXxZZi0566y7Wf&#34;&gt;MIT 6.172 Performance Engineering of Software Systems, Fall 2018&lt;/a&gt;
                by &lt;a href=&#34;https://www.youtube.com/@MIT%20OpenCourseWare&#34;&gt;MIT OpenCourseWare&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;http://graphics.stanford.edu/~seander/bithacks.html#RoundUpPowerOf2&#34;&gt;Bit Twiddling Hacks&lt;/a&gt; by &lt;a href=&#34;https://graphics.stanford.edu/~seander/&#34;&gt;Sean Eron Anderson&lt;/a&gt; at &lt;a href=&#34;https://graphics.stanford.edu&#34;&gt;Stanford Computer Graphics Laboratory&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Knuth &lt;a href=&#34;https://www-cs-faculty.stanford.edu/~knuth/taocp.html&#34;&gt;TAOCP&lt;/a&gt;, 4A section 7.1.3&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;example-code&#34;&gt;Example Code&lt;/h3&gt;
&lt;p&gt;&lt;a href=&#34;https://cpulator.01xz.net/?sys=arm-de1soc&amp;amp;d_audio=48000&amp;amp;loadasm=share/skLx63e.s&#34;&gt;emulator link&lt;/a&gt;&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-asm&#34; data-lang=&#34;asm&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;.global&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;_start&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#91d7e3&#34;&gt;_start:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//-------------------------------------------------
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;  &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//Adding new 1 bits
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;  
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#8aadf4&#34;&gt;MOV&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;R0&lt;/span&gt;, &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#1
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;  &lt;span style=&#34;color:#8aadf4&#34;&gt;ORR&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;R0&lt;/span&gt;, &lt;span style=&#34;color:#eed49f&#34;&gt;R0&lt;/span&gt;, &lt;span style=&#34;color:#eed49f&#34;&gt;LSL&lt;/span&gt; &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#6 //R0 will now have 1 bit at 0 and 5
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;  
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//-------------------------------------------------
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;  &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//Using TST
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;  &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//TST compares two values with an AND, discarding result, 
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;  &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//but sets zero flag if the result of the operation was 0
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;  &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//So if the two values have ANY bits the same ZF == 0
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;  
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//R0 is 0x41
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;  &lt;span style=&#34;color:#8aadf4&#34;&gt;TST&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;R0&lt;/span&gt;, &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#1  //result of AND is 1, ZF == 0
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;  &lt;span style=&#34;color:#8aadf4&#34;&gt;TST&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;R0&lt;/span&gt;, &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#0x40 //result of AND is 0x40, ZF == 0
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;  
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#8aadf4&#34;&gt;MOV&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;R1&lt;/span&gt;, &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#0
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;  &lt;span style=&#34;color:#8aadf4&#34;&gt;TST&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;R1&lt;/span&gt;, &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#1  //result of AND is 0, ZF == 1
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;  &lt;span style=&#34;color:#8aadf4&#34;&gt;TST&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;R1&lt;/span&gt;, &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#64 //result of AND is 0, ZF == 1
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;  
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#8aadf4&#34;&gt;MOV&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;R1&lt;/span&gt;, &lt;span style=&#34;color:#eed49f&#34;&gt;R0&lt;/span&gt;, &lt;span style=&#34;color:#eed49f&#34;&gt;LSL&lt;/span&gt; &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#6 //R1 will have a bit at 5 and 11 
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;  &lt;span style=&#34;color:#8aadf4&#34;&gt;TST&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;R1&lt;/span&gt;, &lt;span style=&#34;color:#eed49f&#34;&gt;R0&lt;/span&gt; &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//have bits in common, ZF 0
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;  
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#8aadf4&#34;&gt;MOV&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;R0&lt;/span&gt;, &lt;span style=&#34;color:#eed49f&#34;&gt;R1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#8aadf4&#34;&gt;TST&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;R1&lt;/span&gt;, &lt;span style=&#34;color:#eed49f&#34;&gt;R0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//EQ and NE are named for the CMP results (which does a SUB)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;  &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//So results confusing. 
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;  &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//BEQ to branch when ZF == 1  //has no things in common
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;  &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//BNE to branch when ZF == 0  //has some things in common
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;  
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//-------------------------------------------------
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;  &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//Set specific bits to zero
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;  &lt;span style=&#34;color:#8aadf4&#34;&gt;LDR&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;R0&lt;/span&gt;, &lt;span style=&#34;color:#ed8796&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#f5a97f&#34;&gt;0xAAAAAAAA&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#8aadf4&#34;&gt;MOV&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;R1&lt;/span&gt;, &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#10  //put an a in the 0 position
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;  &lt;span style=&#34;color:#8aadf4&#34;&gt;LSLS&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;R1&lt;/span&gt;, &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#12 //move the a to the 3rd position (4*3)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;  
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//Performs XOR operation
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;  &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//on bits of Rn with bits of Rm.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;  &lt;span style=&#34;color:#8aadf4&#34;&gt;EORS&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;R2&lt;/span&gt;, &lt;span style=&#34;color:#eed49f&#34;&gt;R0&lt;/span&gt;, &lt;span style=&#34;color:#eed49f&#34;&gt;R1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//Performs AND operation
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;  &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//on bits of Rn with ~bits of Rm.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;  &lt;span style=&#34;color:#8aadf4&#34;&gt;BICS&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;R3&lt;/span&gt;, &lt;span style=&#34;color:#eed49f&#34;&gt;R0&lt;/span&gt;, &lt;span style=&#34;color:#eed49f&#34;&gt;R1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//Looks the same? Not quite!
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;  
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//0xA == 0b1010, 0x2 = 0b0010
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;  &lt;span style=&#34;color:#8aadf4&#34;&gt;LDR&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;R4&lt;/span&gt;, &lt;span style=&#34;color:#ed8796&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#f5a97f&#34;&gt;0x22222222&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#8aadf4&#34;&gt;ORR&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;R5&lt;/span&gt;, &lt;span style=&#34;color:#eed49f&#34;&gt;R4&lt;/span&gt;, &lt;span style=&#34;color:#eed49f&#34;&gt;R1&lt;/span&gt;   &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//Adds missing bits =&amp;gt; 0b1010
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;  &lt;span style=&#34;color:#8aadf4&#34;&gt;EORS&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;R5&lt;/span&gt;, &lt;span style=&#34;color:#eed49f&#34;&gt;R4&lt;/span&gt;, &lt;span style=&#34;color:#eed49f&#34;&gt;R1&lt;/span&gt;  &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//removes where duplicated =&amp;gt; 0b1000
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;  &lt;span style=&#34;color:#8aadf4&#34;&gt;BICS&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;R5&lt;/span&gt;, &lt;span style=&#34;color:#eed49f&#34;&gt;R4&lt;/span&gt;, &lt;span style=&#34;color:#eed49f&#34;&gt;R1&lt;/span&gt;  &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//removes where mask (R1) is 1 =&amp;gt; 0b0000
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;  
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//-------------------------------------------------
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;  &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//Retrieve selective chunk with mask
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;  &lt;span style=&#34;color:#8aadf4&#34;&gt;MOV&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;R0&lt;/span&gt;, &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#0xFF
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;  &lt;span style=&#34;color:#8aadf4&#34;&gt;LSL&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;R0&lt;/span&gt;, &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#16 //(4*N)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;  &lt;span style=&#34;color:#8aadf4&#34;&gt;AND&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;R5&lt;/span&gt;, &lt;span style=&#34;color:#eed49f&#34;&gt;R4&lt;/span&gt;, &lt;span style=&#34;color:#eed49f&#34;&gt;R0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#8aadf4&#34;&gt;LSR&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;R5&lt;/span&gt;, &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#16  //if need it down in lowest part
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//-------------------------------------------------
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;  &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//Isolate selective chunk no mask
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;  &lt;span style=&#34;color:#8aadf4&#34;&gt;LDR&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;R0&lt;/span&gt;, &lt;span style=&#34;color:#ed8796&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#0x22FF2222
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;  &lt;span style=&#34;color:#8aadf4&#34;&gt;LSL&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;R0&lt;/span&gt;, &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#8 //(4*N)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;  &lt;span style=&#34;color:#8aadf4&#34;&gt;LSR&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;R0&lt;/span&gt;, &lt;span style=&#34;color:#f5a97f&#34;&gt;24&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//-------------------------------------------------
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;  &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//Set selective chunk
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;  
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#8aadf4&#34;&gt;LSL&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;R0&lt;/span&gt;, &lt;span style=&#34;color:#f5a97f&#34;&gt;24&lt;/span&gt; &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//mask to clear target area
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;  &lt;span style=&#34;color:#8aadf4&#34;&gt;BICS&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;R4&lt;/span&gt;, &lt;span style=&#34;color:#eed49f&#34;&gt;R0&lt;/span&gt; &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//clean out the bit area in target
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#8aadf4&#34;&gt;MOV&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;R1&lt;/span&gt;, &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#0xAA  //put desired value in a register
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;  &lt;span style=&#34;color:#8aadf4&#34;&gt;ORR&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;R4&lt;/span&gt;, &lt;span style=&#34;color:#eed49f&#34;&gt;R1&lt;/span&gt;, &lt;span style=&#34;color:#eed49f&#34;&gt;LSL&lt;/span&gt; &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#16 //orr clean target with shifted new value
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;  
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;conditional-branching-with-the-thumb-1-instructions-set&#34;&gt;Conditional Branching with the Thumb-1 Instructions Set&lt;/h2&gt;
&lt;p&gt;What&amp;rsquo;s another thing you won&amp;rsquo;t see in any of the code for the SAMD21E18A? Most of the compound conditional instructions. (cc place holder for conditional code)&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;BLcc &lt;label&gt; (Bcc okay though)&lt;/li&gt;
&lt;li&gt;MOVcc Rd Rm&lt;/li&gt;
&lt;li&gt;IT cc&amp;hellip;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Cortex-M0/Cortex-M0+ chips use Arm v6, which means the thumb v1 instruction set, &lt;a href=&#34;https://stackoverflow.com/questions/28669905/what-is-the-difference-between-the-arm-thumb-and-thumb-2-instruction-encodings&#34;&gt;which means NONE&lt;/a&gt; of the &lt;a href=&#34;https://azeria-labs.com/arm-conditional-execution-and-branching-part-6/&#34;&gt;conditional niceties&lt;/a&gt; available to their bigger siblings. I&amp;rsquo;m not used to assembly having them anyway, but much of the example code out there seems to target M3 or higher. It just won&amp;rsquo;t compile with the &lt;code&gt;-mcpu=cortex-m0plus&lt;/code&gt; &lt;a href=&#34;https://s-o-c.org/setting-cpu-targets-for-arm-compilation-with-gcc/&#34;&gt;flag set&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&#34;references-1&#34;&gt;References&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;See also the links in the above ¶&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://community.arm.com/arm-community-blogs/b/architectures-and-processors-blog/posts/armv6-m-vs-armv7-m---unpacking-the-microcontrollers&#34;&gt;armv6 vs armv7&lt;/a&gt; overview from &lt;a href=&#34;https://community.arm.com/&#34;&gt;Arm community&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://documentation-service.arm.com/static/5e7b6a6216d2907d594035c4&#34;&gt;Instruction Set Assembly Guide for Armv7 and earlier Arm architectures&lt;/a&gt; from &lt;a href=&#34;https://www.arm.com&#34;&gt;Arm&lt;/a&gt; documentation service&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://www.arm.com/-/media/Arm%20Developer%20Community/PDF/Processor%20Datasheets/Arm%20Cortex-M0%20plus%20Processor%20Datasheet.pdf&#34;&gt;Arm Cortex-M0+ DataSheet&lt;/a&gt; from &lt;a href=&#34;https://www.arm.com&#34;&gt;Arm&lt;/a&gt; contains image below. Figure 5, page 6.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src=&#34;instruction_set_compare.png&#34; alt=&#34;Image that compares what assembly instructions that are available accross the Coretex-M family. From the Cortex-M0+ data sheet. Figure 5, page 6 &#34;&gt;&lt;/p&gt;
&lt;h3 id=&#34;example-code-1&#34;&gt;Example Code&lt;/h3&gt;
&lt;p&gt;What does that difference look like in practice? In full Arm syntax, &lt;code&gt;BLNE&lt;/code&gt;  (branch with link if Z!=0) can be called with no fuss.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-asm&#34; data-lang=&#34;asm&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//full syntax
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//.syntax unified
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//.arm //might also see as .code 32
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;  &lt;span style=&#34;color:#8aadf4&#34;&gt;TST&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;R0&lt;/span&gt;, &lt;span style=&#34;color:#eed49f&#34;&gt;R4&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#8aadf4&#34;&gt;BLNE&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;doIfAnySwitch&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//continue...
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;In thumb2 &lt;code&gt;BLNE&lt;/code&gt; can be called inside an &lt;a href=&#34;https://community.arm.com/arm-community-blogs/b/architectures-and-processors-blog/posts/condition-codes-3-conditional-execution-in-thumb-2&#34;&gt;IT block&lt;/a&gt;.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-asm&#34; data-lang=&#34;asm&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//on armv7, thumb2 capable chips
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//.syntax unified
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//.thumb //might also see as .code 16
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;  &lt;span style=&#34;color:#8aadf4&#34;&gt;TST&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;R0&lt;/span&gt;, &lt;span style=&#34;color:#eed49f&#34;&gt;R4&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#8aadf4&#34;&gt;IT&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;NE&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#8aadf4&#34;&gt;BLNE&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;doIfAnySwitch&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//continue...
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;In thumb1 &lt;code&gt;BLNE&lt;/code&gt; doesn&amp;rsquo;t exist at all but &lt;code&gt;BEQ&lt;/code&gt; and &lt;code&gt;BNE&lt;/code&gt; do. The best call will be to look for the negative branch condition instead and jump past the branch instead.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-asm&#34; data-lang=&#34;asm&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//------ thumb1 style only
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//on armv6, thumb 1 only
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//.syntax divided 
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//.thumb //might also see as .code 16
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;  &lt;span style=&#34;color:#8aadf4&#34;&gt;TST&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;R0&lt;/span&gt;, &lt;span style=&#34;color:#eed49f&#34;&gt;R4&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#8aadf4&#34;&gt;BEQ&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;skipBranch&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#8aadf4&#34;&gt;BL&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;doIfAnySwitch&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#91d7e3&#34;&gt;skipBranch:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//continue...
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;So if you&amp;rsquo;re wondering why my switch code doesn&amp;rsquo;t use any of the fancy branching syntax you&amp;rsquo;ve seen in other places, that&amp;rsquo;s why.&lt;/p&gt;
&lt;h2 id=&#34;calling-conventions&#34;&gt;Calling Conventions&lt;/h2&gt;
&lt;p&gt;It&amp;rsquo;s finally time to touch on proper sub routine &lt;a href=&#34;https://en.wikipedia.org/wiki/Calling_convention#ARM_(A32)&#34;&gt;calling conventions&lt;/a&gt;. The TL;DR&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Don&amp;rsquo;t trust R0-R3 to stay the way you left them (&amp;ldquo;callee clobbered&amp;rdquo;)&lt;/li&gt;
&lt;li&gt;Put R4-R11 and the stack pointer (&amp;ldquo;SP&amp;rdquo;) need to be put back the way th callee found them (&amp;ldquo;callee preserved&amp;rdquo;).&lt;/li&gt;
&lt;li&gt;R12-R15 the system can alter at any time&lt;/li&gt;
&lt;li&gt;Subroutines with subroutines have to deal with the original LR being &amp;ldquo;clobbered&amp;rdquo;, but can handle that by putting their desired &amp;ldquo;LR&amp;rdquo; back into &amp;ldquo;PC&amp;rdquo; themselves.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;It&amp;rsquo;s up to the programmer to play nice with expectations, and each manufacturer has slight variations on top of the Arm standard to be aware of.&lt;/p&gt;
&lt;h3 id=&#34;register-conventions-for-sam-mcus&#34;&gt;Register Conventions for SAM MCUs&lt;/h3&gt;
&lt;table class=&#34;foo2&#34;&gt;
  &lt;thead&gt;
      &lt;tr&gt;
          &lt;th style=&#34;text-align: left&#34;&gt;Register&lt;/th&gt;
          &lt;th style=&#34;text-align: left&#34;&gt;Label&lt;/th&gt;
          &lt;th style=&#34;text-align: left&#34;&gt;Role&lt;/th&gt;
      &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
      &lt;tr&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;R0&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;argument/result/scratch register 1&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;R1&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;argument/result/scratch register 2&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;R1&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;argument/scratch register 3&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;R3&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;argument/scratch register 4&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;R4&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;variable register 1&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;R5&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;variable register 2&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;R6&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;variable register 3&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;R7&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;variable register 4&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;R8&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;variable register 5*&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;R9&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;variable register 6*&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;R10&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;variable register 7*&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;R11&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;variable register 8*&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;R12&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;IP&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;Intra-procedure call scratch register*‡&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;R13&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;SP&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;Stack pointer&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;R14&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;LR&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;Link Register&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;R15&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;PC&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;Program Counter&lt;/td&gt;
      &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;ul&gt;
&lt;li&gt;* In the M0 and M0+ spec, registers above R7 have limitations. Only R0-R7, the low registers, can uniformly be accessed by all instructions. The higher registers can only be accessed by add, blx, bx, cmp, mov (not movs), msr, mrs. This is indicated in the &lt;a href=&#34;https://developer.arm.com/documentation/ddi0484/c/?lang=en&#34;&gt;Cortex-M0+ Technical Reference Manual (Revision: r0p1)&lt;/a&gt; section 3.3 as some functions only being able to use with &amp;ldquo;Lo&amp;rdquo; (R0-R7) vs &amp;ldquo;Any&amp;rdquo;, See also A4.1 in the &lt;a href=&#34;https://documentation-service.arm.com/static/5f8ff05ef86e16515cdbf826&#34;&gt;ARMv6-M Architecture Reference Manual&lt;/a&gt; for a brief mention&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&#34;references-2&#34;&gt;References&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;StackOverflow discussion &lt;a href=&#34;https://stackoverflow.com/questions/261419/what-registers-to-save-in-the-arm-c-calling-convention&#34;&gt;on what registers to save for Arm&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Microchip &lt;a href=&#34;https://onlinedocs.microchip.com/oxy/GUID-BE362C91-6400-481F-9D86-10A1C40CA77C-en-US-4/GUID-659F7E34-45AE-4EDD-B596-9CF69A5C4DEF.html&#34;&gt;Register Conventions Guide&lt;/a&gt; for Pic32C/SAM MCUS&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://eecs.umich.edu/courses/eecs373/readings/ARM-AAPCS-EABI-v2.08.pdf&#34;&gt;Procedure Call Standard for the
ARM® Architecture v2.08&lt;/a&gt; (Older doc, linked to from &lt;a href=&#34;https://eecs.umich.edu/courses/eecs373/&#34;&gt;UMich EECS 373&lt;/a&gt; website.)&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/FFmpeg/FFmpeg/blob/release/7.0/libavcodec/arm/me_cmp_armv6.S&#34;&gt;Example of push/pop in the wild&lt;/a&gt; from &lt;a href=&#34;https://github.com/FFmpeg/FFmpeg/&#34;&gt;FFMPEG&lt;/a&gt; code base&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://software-dl.ti.com/codegen/docs/tiarmclang/compiler_tools_user_guide/compiler_manual/runtime_environment/function-structure-and-calling-conventions-stdz0545494.html&#34;&gt;Relationship to C function&lt;/a&gt; calls from TI&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://mcyoung.xyz/2024/04/17/calling-convention/&#34;&gt;&amp;ldquo;The Rust Calling Convention We Deserve&amp;rdquo;&lt;/a&gt; mcyoung&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;code-example&#34;&gt;Code Example&lt;/h3&gt;
&lt;p&gt;It doesn&amp;rsquo;t do the full &amp;ldquo;prologue&amp;rdquo; and &amp;ldquo;epilogue&amp;rdquo; one might see in complicated programs, but it&amp;rsquo;s a start.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://cpulator.01xz.net/?sys=arm-de1soc&amp;amp;d_audio=48000&amp;amp;loadasm=share/sYZ6HsI.s&#34;&gt;emulator&lt;/a&gt;&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-asm&#34; data-lang=&#34;asm&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;.syntax&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;unified&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;.global&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;_start&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#91d7e3&#34;&gt;_start:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#8aadf4&#34;&gt;MOV&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;R4&lt;/span&gt;,  &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#0xAA
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;  &lt;span style=&#34;color:#8aadf4&#34;&gt;MOV&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;R5&lt;/span&gt;,  &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#0xAB
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;  &lt;span style=&#34;color:#8aadf4&#34;&gt;MOV&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;R6&lt;/span&gt;,  &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#0xAC
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;  &lt;span style=&#34;color:#8aadf4&#34;&gt;MOV&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;R7&lt;/span&gt;,  &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#0xAD //NOTE: regs above 7 have limits in
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;  &lt;span style=&#34;color:#8aadf4&#34;&gt;MOV&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;R8&lt;/span&gt;,  &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#0xAE //CM0/CM0+ chips. can only use with
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;  &lt;span style=&#34;color:#8aadf4&#34;&gt;MOV&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;R9&lt;/span&gt;,  &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#0xAF //add, blx, bx, cmp, mov, msr, mrs
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;  &lt;span style=&#34;color:#8aadf4&#34;&gt;MOV&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;R10&lt;/span&gt;, &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#0xBA 
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;  &lt;span style=&#34;color:#8aadf4&#34;&gt;MOV&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;R11&lt;/span&gt;, &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#0xBC
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;  
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#91d7e3&#34;&gt;loop:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#8aadf4&#34;&gt;MOV&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;R0&lt;/span&gt;, &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#1
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#8aadf4&#34;&gt;MOV&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;R1&lt;/span&gt;, &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#2
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#8aadf4&#34;&gt;MOV&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;R2&lt;/span&gt;, &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#3
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#8aadf4&#34;&gt;MOV&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;R3&lt;/span&gt;, &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#4
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#8aadf4&#34;&gt;BL&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;subCallWithSubCall&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//R4-R11 will look exactly the same
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//R0-R3 will be entirely different
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//R0 will have possible return value
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//sp is back to zero
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;  &lt;span style=&#34;color:#8aadf4&#34;&gt;B&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;loop&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#91d7e3&#34;&gt;subCallWithSubCall:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#8aadf4&#34;&gt;PUSH&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;{&lt;/span&gt;&lt;span style=&#34;color:#eed49f&#34;&gt;R4-R11&lt;/span&gt;, &lt;span style=&#34;color:#eed49f&#34;&gt;LR&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#8aadf4&#34;&gt;PUSH&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;{&lt;/span&gt;&lt;span style=&#34;color:#eed49f&#34;&gt;R0-R3&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;}&lt;/span&gt; &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//move R0-R3 
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;  &lt;span style=&#34;color:#8aadf4&#34;&gt;POP&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;{&lt;/span&gt;&lt;span style=&#34;color:#eed49f&#34;&gt;R4-R7&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;}&lt;/span&gt;  &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//into R4-R7
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#8aadf4&#34;&gt;ADD&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;R1&lt;/span&gt;, &lt;span style=&#34;color:#eed49f&#34;&gt;R5&lt;/span&gt;, &lt;span style=&#34;color:#eed49f&#34;&gt;R6&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#8aadf4&#34;&gt;ADD&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;R2&lt;/span&gt;, &lt;span style=&#34;color:#eed49f&#34;&gt;R7&lt;/span&gt;, &lt;span style=&#34;color:#eed49f&#34;&gt;R8&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#8aadf4&#34;&gt;ADD&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;R3&lt;/span&gt;, &lt;span style=&#34;color:#eed49f&#34;&gt;R8&lt;/span&gt;, &lt;span style=&#34;color:#eed49f&#34;&gt;R9&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#8aadf4&#34;&gt;PUSH&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;{&lt;/span&gt;&lt;span style=&#34;color:#eed49f&#34;&gt;R1-R3&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;}&lt;/span&gt; &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//save my calculations
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;  &lt;span style=&#34;color:#8aadf4&#34;&gt;BL&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;leafCall&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#8aadf4&#34;&gt;POP&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;{&lt;/span&gt;&lt;span style=&#34;color:#eed49f&#34;&gt;R1-R3&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;}&lt;/span&gt; &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//retrieve them.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;  &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//R0 has &amp;#34;result of leafCall&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#8aadf4&#34;&gt;CMP&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;R0&lt;/span&gt;, &lt;span style=&#34;color:#eed49f&#34;&gt;R10&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#8aadf4&#34;&gt;MOVLT&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;R0&lt;/span&gt;, &lt;span style=&#34;color:#eed49f&#34;&gt;R10&lt;/span&gt; &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//wouldn&amp;#39;t be possible in thumb1
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;  &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//R0 has result of this routine
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;POP&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;{&lt;/span&gt;&lt;span style=&#34;color:#eed49f&#34;&gt;R4-R11&lt;/span&gt;, &lt;span style=&#34;color:#eed49f&#34;&gt;PC&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;}&lt;/span&gt; &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//no BX LR b/c return was handled by 
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;         &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//direct load of saved LR into PC
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#91d7e3&#34;&gt;leafCall:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#8aadf4&#34;&gt;PUSH&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;{&lt;/span&gt;&lt;span style=&#34;color:#eed49f&#34;&gt;R4-R11&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;}&lt;/span&gt; &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//J.I.C. would remove really. 
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#8aadf4&#34;&gt;ADD&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;R1&lt;/span&gt;, &lt;span style=&#34;color:#eed49f&#34;&gt;R5&lt;/span&gt;, &lt;span style=&#34;color:#eed49f&#34;&gt;R6&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#8aadf4&#34;&gt;ADD&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;R2&lt;/span&gt;, &lt;span style=&#34;color:#eed49f&#34;&gt;R7&lt;/span&gt;, &lt;span style=&#34;color:#eed49f&#34;&gt;R5&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#8aadf4&#34;&gt;ADD&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;R0&lt;/span&gt;, &lt;span style=&#34;color:#eed49f&#34;&gt;R1&lt;/span&gt;, &lt;span style=&#34;color:#eed49f&#34;&gt;R2&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#8aadf4&#34;&gt;POP&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;{&lt;/span&gt;&lt;span style=&#34;color:#eed49f&#34;&gt;R4-R11&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;BX&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;LR&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;setting-pullups&#34;&gt;Setting pullups&lt;/h2&gt;
&lt;p&gt;Using the data gleaned in the &lt;a href=&#34;https://whynotestflight.com/excuses/its-alive-samd21e18a-assembly-no-sdk/#what-about-when-i-want-a-to-add-a-switch&#34;&gt;last post&lt;/a&gt;, I wrote three different versions of setting the pullup resistor for my switch on PA07.&lt;/p&gt;
&lt;h3 id=&#34;v1---inline-hard-coded&#34;&gt;V1 - inline, hard coded&lt;/h3&gt;
&lt;p&gt;I gave this code a label so I could set a break point, but it lives inline before the loop as you can see in the repo (link below).&lt;/p&gt;
&lt;p&gt;The biggest gotcha was picking the address to put in &lt;code&gt;switchPinCNFGOffset&lt;/code&gt; because to use &lt;code&gt;LDR&lt;/code&gt; that address &lt;a href=&#34;https://developer.arm.com/documentation/dui0497/a/the-cortex-m0-instruction-set/memory-access-instructions/ldr-and-str--immediate-offset&#34;&gt;has to be divisible by 4&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;So instead of &lt;code&gt;portA_PINCNFG+0x07&lt;/code&gt;, it&amp;rsquo;s &lt;code&gt;portA_PINCNFG+0x04&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;I show loading a specific byte in the later examples, but I thought this was a good lesson. To use word aligned data I fetched the nearest but lower aligned location and shifted the needed bits up to the last byte to match the 7 total offset.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://github.com/carlynorama/StrippedDownChipRosetta/tree/main/ARM/SAMD21E18/04_AssemblySwtich/a_directPinSwap/main.s&#34;&gt;in repo&lt;/a&gt;&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-asm&#34; data-lang=&#34;asm&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#91d7e3&#34;&gt;setPullup:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//---- For using internal pullup only
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;  &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//switchPinCNFGOffset == portA_PINCNFG+0x04 
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;LDR&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;R5&lt;/span&gt;, &lt;span style=&#34;color:#ed8796&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#eed49f&#34;&gt;switchPinCNFGOffset&lt;/span&gt; &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//pinConfig closest word location
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;  &lt;span style=&#34;color:#8aadf4&#34;&gt;LDR&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;R0&lt;/span&gt;, [&lt;span style=&#34;color:#eed49f&#34;&gt;R5&lt;/span&gt;] &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//load current settings into R0
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;  &lt;span style=&#34;color:#8aadf4&#34;&gt;MOVS&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;R1&lt;/span&gt;, &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#6 //create value for INEN 1 (bit 1) //set PULLEN 1 (bit 2)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;  &lt;span style=&#34;color:#8aadf4&#34;&gt;LSLS&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;R1&lt;/span&gt;, &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#24 //(8*(7-4)) //move it from 4 to 7
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;  &lt;span style=&#34;color:#8aadf4&#34;&gt;ORRS&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;R0&lt;/span&gt;, &lt;span style=&#34;color:#eed49f&#34;&gt;R1&lt;/span&gt; &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//apply mask
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;  &lt;span style=&#34;color:#8aadf4&#34;&gt;STR&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;R0&lt;/span&gt;, [&lt;span style=&#34;color:#eed49f&#34;&gt;R5&lt;/span&gt;] &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//put the updated word back into the config.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;  &lt;span style=&#34;color:#8aadf4&#34;&gt;LDR&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;R5&lt;/span&gt;, &lt;span style=&#34;color:#ed8796&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#eed49f&#34;&gt;portA_OUTSET&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#8aadf4&#34;&gt;STR&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;R4&lt;/span&gt;, [&lt;span style=&#34;color:#eed49f&#34;&gt;R5&lt;/span&gt;] &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//set the out of the switch high
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;  &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//--- END setting internal pullup
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;v2---one-pin-per-branch&#34;&gt;V2 - one pin per branch&lt;/h3&gt;
&lt;p&gt;This code takes the pin number in R0 and sets the config for that pin.  I don&amp;rsquo;t bother pushing R4-R7 because I carefully don&amp;rsquo;t touch them.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://github.com/carlynorama/StrippedDownChipRosetta/blob/main/ARM/SAMD21E18/04_AssemblySwtich/b_conditionalBranch/main.s&#34;&gt;in repo&lt;/a&gt;&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-asm&#34; data-lang=&#34;asm&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//Set R0 to contain the pin number
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//function uses R0-R3 
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;.word&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;setPullup&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;.thumb_func&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#91d7e3&#34;&gt;setPullup:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//Get base address
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;  &lt;span style=&#34;color:#8aadf4&#34;&gt;LDR&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;R1&lt;/span&gt;, &lt;span style=&#34;color:#ed8796&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#eed49f&#34;&gt;portA_PINCNFG&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//LDRB will allow byte call
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;  &lt;span style=&#34;color:#8aadf4&#34;&gt;LDRB&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;R2&lt;/span&gt;, [&lt;span style=&#34;color:#eed49f&#34;&gt;R1&lt;/span&gt;, &lt;span style=&#34;color:#eed49f&#34;&gt;R0&lt;/span&gt;] &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// CFG base, with immediate offset (R0==pin #)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#8aadf4&#34;&gt;MOVS&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;R3&lt;/span&gt;, &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#6 // INEN 1 (bit 1) //set PULLEN 1 (bit 2)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;  &lt;span style=&#34;color:#8aadf4&#34;&gt;ORRS&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;R2&lt;/span&gt;, &lt;span style=&#34;color:#eed49f&#34;&gt;R3&lt;/span&gt; &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// update retrieved settings with new settings
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//Must save with STRB
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;  &lt;span style=&#34;color:#8aadf4&#34;&gt;STRB&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;R2&lt;/span&gt;, [&lt;span style=&#34;color:#eed49f&#34;&gt;R1&lt;/span&gt;, &lt;span style=&#34;color:#eed49f&#34;&gt;R0&lt;/span&gt;] 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//Make pull UP by setting high 
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;  &lt;span style=&#34;color:#8aadf4&#34;&gt;LDR&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;R1&lt;/span&gt;, &lt;span style=&#34;color:#ed8796&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#eed49f&#34;&gt;portA_OUTSET&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#8aadf4&#34;&gt;MOVS&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;R2&lt;/span&gt;, &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#1
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;  &lt;span style=&#34;color:#8aadf4&#34;&gt;LSLS&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;R2&lt;/span&gt;, &lt;span style=&#34;color:#eed49f&#34;&gt;R0&lt;/span&gt; &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//move the bit to the pin pos
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;  &lt;span style=&#34;color:#8aadf4&#34;&gt;STR&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;R2&lt;/span&gt;, [&lt;span style=&#34;color:#eed49f&#34;&gt;R1&lt;/span&gt;] &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//set the out of the switch pin high
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;  &lt;span style=&#34;color:#8aadf4&#34;&gt;BX&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;lr&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;v3---batch-set&#34;&gt;V3 - batch set&lt;/h3&gt;
&lt;p&gt;This code uses the &lt;code&gt;WRCONFIG&lt;/code&gt; address to batch set multiple pins. See page 383, Section 23.8.11 in the &lt;a href=&#34;https://ww1.microchip.com/downloads/aemDocuments/documents/MCU32/ProductDocuments/DataSheets/SAM-D21-DA1-Family-Data-Sheet-DS40001882H.pdf&#34;&gt;Family Datasheet&lt;/a&gt;. I don&amp;rsquo;t need it for this code, but since they provide the address I wanted to show it!&lt;/p&gt;
&lt;p&gt;Using the WRCONFIG address can set up to 16 pins in the same half of a pin group that should share the same configuration all the same time.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;WRCONFIG_PINS.png&#34; alt=&#34;Screenshot of bit layout of WRCONFIG from page 371 of the family datasheet (23.7 Register Summary)&#34;&gt;&lt;/p&gt;
&lt;table class=&#34;odd&#34;&gt;
  &lt;thead&gt;
      &lt;tr&gt;
          &lt;th style=&#34;text-align: left&#34;&gt;Bit&lt;/th&gt;
          &lt;th style=&#34;text-align: left&#34;&gt;Name&lt;/th&gt;
          &lt;th style=&#34;text-align: left&#34;&gt;Acronym&lt;/th&gt;
          &lt;th style=&#34;text-align: left&#34;&gt;Usage&lt;/th&gt;
      &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
      &lt;tr&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;0-15&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;Pin mask&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;PINMASK&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;1: set values for this pin, 0: ignore&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;16&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;Peripheral Multiplexing Enable&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;PMUXEN&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;1: enabled , 0: disabled (0 in PINCFG)&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;17&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;Input Enable&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;INEN&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;1: pin is input, 0: pin is output (1 in PINCFG)&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;18&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;Pull Enable&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;PULLEN&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;1: pull enabled , 0: pull disabled (2 in PINCFG)&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;19&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;&amp;mdash;&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;&amp;mdash;&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;No setting in SAMD21&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;20&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;&amp;mdash;&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;&amp;mdash;&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;No setting in SAMD21&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;21&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;&amp;mdash;&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;&amp;mdash;&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;No setting in SAMD21&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;22&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;Output Driver Strength Selection&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;DRVSTR&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;0 normal 1 strong (6 in PINCFG)&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;23&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;&amp;mdash;&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;&amp;mdash;&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;No setting in SAMD21&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;24-27&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;Peripheral Multiplexing&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;PMUX&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;see 23.8.12 and Sec. 7&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;28&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;-N&amp;ndash;&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;WRPMUX&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;Should update PMUX (1, yes, 0 will ignore)&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;29&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;&amp;mdash;&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;&amp;mdash;&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;No setting in SAMD21&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;30&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;Write PINCFG&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;WRPINCNFG&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;Should update PINCFGs (1: yes, 0: will ignore)&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;31&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;Half-Word Select&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;HWSEL&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;Indicates if 0-15 are the lower (0) or higher (1) pins&lt;/td&gt;
      &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;This code takes in the whole 32 pin group and splits it into the necessary two batches.&lt;/p&gt;
&lt;p&gt;Again this code carefully avoids spilling over past R3. It doesn&amp;rsquo;t use a conditional linked branch to a sub routine that does the repeated tasks of pairing a setting with a half-pin-group and loading it to the register. Little austerities that probably wouldn&amp;rsquo;t make sense to a functional programming mindset without knowing the thumb1 assembly context.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://cpulator.01xz.net/?sys=arm-de1soc&amp;amp;d_audio=48000&amp;amp;loadasm=share/swQlAxG.s&#34;&gt;mock version in emulator&lt;/a&gt;&lt;br&gt;
&lt;a href=&#34;https://github.com/carlynorama/StrippedDownChipRosetta/blob/main/ARM/SAMD21E18/04_AssemblySwtich/b_conditionalBranch/main.s&#34;&gt;in repo&lt;/a&gt;&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-asm&#34; data-lang=&#34;asm&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;.word&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;multiPinPullup&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;.thumb_func&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#91d7e3&#34;&gt;multiPinPullup:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//Go ahead and set the ups
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;  &lt;span style=&#34;color:#8aadf4&#34;&gt;LDR&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;R1&lt;/span&gt;, &lt;span style=&#34;color:#ed8796&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#eed49f&#34;&gt;portA_OUTSET&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#8aadf4&#34;&gt;STR&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;R0&lt;/span&gt;, [&lt;span style=&#34;color:#eed49f&#34;&gt;R1&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#8aadf4&#34;&gt;MOVS&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;R2&lt;/span&gt;, &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#1
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;  &lt;span style=&#34;color:#8aadf4&#34;&gt;MOVS&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;R3&lt;/span&gt;, &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#2
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;  &lt;span style=&#34;color:#8aadf4&#34;&gt;RORS&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;R2&lt;/span&gt;, &lt;span style=&#34;color:#eed49f&#34;&gt;R3&lt;/span&gt;  &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// Bit 30 -&amp;gt; 1 to enable PINCFG set
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;  &lt;span style=&#34;color:#8aadf4&#34;&gt;MOVS&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;R3&lt;/span&gt;, &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#6  // INEN 1 (bit 1) //set PULLEN 1 (bit 2)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;  &lt;span style=&#34;color:#8aadf4&#34;&gt;LSLS&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;R3&lt;/span&gt;, &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#16 // move up to 3rd byte
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;  &lt;span style=&#34;color:#8aadf4&#34;&gt;ORRS&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;R3&lt;/span&gt;, &lt;span style=&#34;color:#eed49f&#34;&gt;R2&lt;/span&gt;  &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// Add bit 30 to R3
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#8aadf4&#34;&gt;LDR&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;R2&lt;/span&gt;, &lt;span style=&#34;color:#ed8796&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#0xFFFF
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;  &lt;span style=&#34;color:#8aadf4&#34;&gt;TST&lt;/span&gt;  &lt;span style=&#34;color:#eed49f&#34;&gt;R0&lt;/span&gt;, &lt;span style=&#34;color:#eed49f&#34;&gt;R2&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#8aadf4&#34;&gt;BEQ&lt;/span&gt;  &lt;span style=&#34;color:#eed49f&#34;&gt;mpp_upperHalf&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#8aadf4&#34;&gt;MOVS&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;R1&lt;/span&gt;, &lt;span style=&#34;color:#eed49f&#34;&gt;R0&lt;/span&gt;  &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// copy R0 for editing
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;  &lt;span style=&#34;color:#8aadf4&#34;&gt;AND&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;R1&lt;/span&gt;, &lt;span style=&#34;color:#eed49f&#34;&gt;R2&lt;/span&gt;   &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//isolate bottom half
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;  &lt;span style=&#34;color:#8aadf4&#34;&gt;ORRS&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;R1&lt;/span&gt;, &lt;span style=&#34;color:#eed49f&#34;&gt;R3&lt;/span&gt;  &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// update R1 with settings 
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;  &lt;span style=&#34;color:#8aadf4&#34;&gt;LDR&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;R2&lt;/span&gt;, &lt;span style=&#34;color:#ed8796&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#eed49f&#34;&gt;portA_WRCONFIG&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#8aadf4&#34;&gt;STR&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;R1&lt;/span&gt;, [&lt;span style=&#34;color:#eed49f&#34;&gt;R2&lt;/span&gt;] &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// send WRCONFIG bottom half info
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#91d7e3&#34;&gt;mpp_upperHalf:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#8aadf4&#34;&gt;LDR&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;R1&lt;/span&gt;, &lt;span style=&#34;color:#ed8796&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#0xFFFF0000
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;  &lt;span style=&#34;color:#8aadf4&#34;&gt;TST&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;R0&lt;/span&gt;, &lt;span style=&#34;color:#eed49f&#34;&gt;R1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#8aadf4&#34;&gt;BEQ&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;mpp_exit&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#8aadf4&#34;&gt;LSRS&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;R0&lt;/span&gt;, &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#16 // isolate top half
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;  &lt;span style=&#34;color:#8aadf4&#34;&gt;ORRS&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;R0&lt;/span&gt;, &lt;span style=&#34;color:#eed49f&#34;&gt;R3&lt;/span&gt;  &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// add settings
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;  &lt;span style=&#34;color:#8aadf4&#34;&gt;LSLS&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;R1&lt;/span&gt;, &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#15 // make R1 0x80000000
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;  &lt;span style=&#34;color:#8aadf4&#34;&gt;ORRS&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;R0&lt;/span&gt;, &lt;span style=&#34;color:#eed49f&#34;&gt;R1&lt;/span&gt;  &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// Add top half flag in bit 31
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;  &lt;span style=&#34;color:#8aadf4&#34;&gt;LDR&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;R2&lt;/span&gt;, &lt;span style=&#34;color:#ed8796&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#eed49f&#34;&gt;portA_WRCONFIG&lt;/span&gt; &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//might be this value already. 
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;  &lt;span style=&#34;color:#8aadf4&#34;&gt;STR&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;R0&lt;/span&gt;, [&lt;span style=&#34;color:#eed49f&#34;&gt;R2&lt;/span&gt;] &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// send WRCONFIG top half info
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;  &lt;span style=&#34;color:#91d7e3&#34;&gt;mpp_exit:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#8aadf4&#34;&gt;BX&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;LR&lt;/span&gt;  
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;reacting-to-the-switch&#34;&gt;Reacting to the Switch&lt;/h2&gt;
&lt;p&gt;I wrote two ways to react to the switch values. The first requires knowing the distance between the two pins on the PA register, but doesn&amp;rsquo;t depend on branching. The second uses a TST and BEQ to send the ledMask to OUTCLR or OUTSET.&lt;/p&gt;
&lt;h3 id=&#34;v1---use-the-switch-pin-directly&#34;&gt;V1 - Use the Switch Pin Directly&lt;/h3&gt;
&lt;p&gt;This code never &amp;ldquo;knows&amp;rdquo; what the state of the switch pin is. It sends whatever that state is to the LED&amp;rsquo;s OUTCLR position and it&amp;rsquo;s inverse to OUTSET every time.  (see hardware note)&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://github.com/carlynorama/StrippedDownChipRosetta/tree/main/ARM/SAMD21E18/04_AssemblySwtich/a_directPinSwap/main.s&#34;&gt;in repo&lt;/a&gt;&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-asm&#34; data-lang=&#34;asm&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#8aadf4&#34;&gt;MOVS&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;R4&lt;/span&gt;, &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#1  
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;  &lt;span style=&#34;color:#8aadf4&#34;&gt;LSLS&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;R4&lt;/span&gt;, &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#switchPinOffset
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;  &lt;span style=&#34;color:#8aadf4&#34;&gt;LDR&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;R5&lt;/span&gt;, &lt;span style=&#34;color:#ed8796&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#eed49f&#34;&gt;portA_OUTSET&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#8aadf4&#34;&gt;LDR&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;R6&lt;/span&gt;, &lt;span style=&#34;color:#ed8796&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#eed49f&#34;&gt;portA_OUTCLR&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#8aadf4&#34;&gt;LDR&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;R7&lt;/span&gt;, &lt;span style=&#34;color:#ed8796&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#eed49f&#34;&gt;portA_IN&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#91d7e3&#34;&gt;loop:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//get the value of the IN register (address in R7)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#8aadf4&#34;&gt;LDR&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;R0&lt;/span&gt;, [&lt;span style=&#34;color:#eed49f&#34;&gt;R7&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//Isolate the switch reading 
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#8aadf4&#34;&gt;ANDS&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;R0&lt;/span&gt;, &lt;span style=&#34;color:#eed49f&#34;&gt;R4&lt;/span&gt; &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//should typically be 1, due to pullup resistor
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#8aadf4&#34;&gt;MOVS&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;R1&lt;/span&gt;, &lt;span style=&#34;color:#eed49f&#34;&gt;R0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#8aadf4&#34;&gt;EORS&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;R1&lt;/span&gt;, &lt;span style=&#34;color:#eed49f&#34;&gt;R4&lt;/span&gt; &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//R1 will 1 at the switch bit iff the read was 0
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#8aadf4&#34;&gt;LSLS&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;R0&lt;/span&gt;, &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#3  //move bit 7 (switch) to 10 (led)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#8aadf4&#34;&gt;LSLS&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;R1&lt;/span&gt;, &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#3  //move bit 7 (switch) to 10 (led)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//Sending 0s the to set and clear registers has no effect.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//The state of R0 always matches what should go to CLEAR
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//The state of R1 matches what should be in SET 
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#8aadf4&#34;&gt;STR&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;R0&lt;/span&gt;, [&lt;span style=&#34;color:#eed49f&#34;&gt;R6&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#8aadf4&#34;&gt;STR&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;R1&lt;/span&gt;, [&lt;span style=&#34;color:#eed49f&#34;&gt;R5&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#8aadf4&#34;&gt;B&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;loop&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;v2---test-the-switch-pin&#34;&gt;V2 - Test the Switch Pin&lt;/h3&gt;
&lt;p&gt;Uses separate masks for the led pin and switch pins, but requires navigating conditionals in the thumb 1 instruction set!&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://github.com/carlynorama/StrippedDownChipRosetta/blob/main/ARM/SAMD21E18/04_AssemblySwtich/b_conditionalBranch/main.s&#34;&gt;in repo&lt;/a&gt;&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-asm&#34; data-lang=&#34;asm&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#8aadf4&#34;&gt;MOVS&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;R4&lt;/span&gt;, &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#1
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;  &lt;span style=&#34;color:#8aadf4&#34;&gt;LSLS&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;R3&lt;/span&gt;, &lt;span style=&#34;color:#eed49f&#34;&gt;R4&lt;/span&gt;, &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#ledPinOffset 
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;  &lt;span style=&#34;color:#8aadf4&#34;&gt;LSLS&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;R4&lt;/span&gt;, &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#switchPinOffset
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;  &lt;span style=&#34;color:#8aadf4&#34;&gt;LDR&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;R5&lt;/span&gt;, &lt;span style=&#34;color:#ed8796&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#eed49f&#34;&gt;portA_OUTSET&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#8aadf4&#34;&gt;LDR&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;R6&lt;/span&gt;, &lt;span style=&#34;color:#ed8796&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#eed49f&#34;&gt;portA_OUTCLR&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#8aadf4&#34;&gt;LDR&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;R7&lt;/span&gt;, &lt;span style=&#34;color:#ed8796&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#eed49f&#34;&gt;portA_IN&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#91d7e3&#34;&gt;loop:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//get the value of the IN register
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#8aadf4&#34;&gt;LDR&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;R0&lt;/span&gt;, [&lt;span style=&#34;color:#eed49f&#34;&gt;R7&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//TST the reading against the mask. 
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;                &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//R0 should read 1 at switch location as default
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;                &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//due to pullup resistor so if the AND result
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#8aadf4&#34;&gt;TST&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;R0&lt;/span&gt;, &lt;span style=&#34;color:#eed49f&#34;&gt;R4&lt;/span&gt;  &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//EQUALS 0 (no match), the switch is _closed_ 
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#8aadf4&#34;&gt;BEQ&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;ledOn&lt;/span&gt;   &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//so jump to on
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#91d7e3&#34;&gt;ledOff:&lt;/span&gt;  &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//default path
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#8aadf4&#34;&gt;STR&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;R3&lt;/span&gt;, [&lt;span style=&#34;color:#eed49f&#34;&gt;R6&lt;/span&gt;] &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//R3==ledMask, R6==portA_OUTCLR
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#8aadf4&#34;&gt;B&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;loop&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#91d7e3&#34;&gt;ledOn:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#8aadf4&#34;&gt;STR&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;R3&lt;/span&gt;, [&lt;span style=&#34;color:#eed49f&#34;&gt;R5&lt;/span&gt;] &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//R3==ledMask, R5==portA_OUTSET
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#8aadf4&#34;&gt;B&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;loop&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;complete-mains-examples&#34;&gt;Complete main.s examples&lt;/h2&gt;
&lt;h3 id=&#34;version-1&#34;&gt;Version 1&lt;/h3&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-asm&#34; data-lang=&#34;asm&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;.syntax&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;unified&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;.cpu&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;cortex-m0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;.fpu&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;softvfp&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#eed49f&#34;&gt;.thumb&lt;/span&gt;  
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#eed49f&#34;&gt;.section&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;.text.program_code&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;.equ&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;portA_address&lt;/span&gt;, &lt;span style=&#34;color:#f5a97f&#34;&gt;0x41004400&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;.equ&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;portA_DIRCLR&lt;/span&gt;, &lt;span style=&#34;color:#f5a97f&#34;&gt;0x41004400&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;+&lt;/span&gt;&lt;span style=&#34;color:#f5a97f&#34;&gt;0x04&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;.equ&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;portA_DIRSET&lt;/span&gt;, &lt;span style=&#34;color:#f5a97f&#34;&gt;0x41004400&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;+&lt;/span&gt;&lt;span style=&#34;color:#f5a97f&#34;&gt;0x08&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;.equ&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;portA_OUTCLR&lt;/span&gt;, &lt;span style=&#34;color:#f5a97f&#34;&gt;0x41004400&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;+&lt;/span&gt;&lt;span style=&#34;color:#f5a97f&#34;&gt;0x14&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;.equ&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;portA_OUTSET&lt;/span&gt;, &lt;span style=&#34;color:#f5a97f&#34;&gt;0x41004400&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;+&lt;/span&gt;&lt;span style=&#34;color:#f5a97f&#34;&gt;0x18&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//.equ portA_OUTTGL, 0x41004400+0x1C
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;.equ&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;portA_IN&lt;/span&gt;, &lt;span style=&#34;color:#f5a97f&#34;&gt;0x41004400&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;+&lt;/span&gt;&lt;span style=&#34;color:#f5a97f&#34;&gt;0x20&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;.equ&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;portA_PINCNFG&lt;/span&gt;, &lt;span style=&#34;color:#f5a97f&#34;&gt;0x41004400&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;+&lt;/span&gt;&lt;span style=&#34;color:#f5a97f&#34;&gt;0x40&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;.equ&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;ledPinOffset&lt;/span&gt;, &lt;span style=&#34;color:#f5a97f&#34;&gt;10&lt;/span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//PA10
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;.equ&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;switchPinOffset&lt;/span&gt;, &lt;span style=&#34;color:#f5a97f&#34;&gt;7&lt;/span&gt;  &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//PA07, 
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//this value is NOT 7 because use LDR below
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//which requires a word alignment
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;.equ&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;switchPinCNFGOffset&lt;/span&gt;, &lt;span style=&#34;color:#eed49f&#34;&gt;portA_PINCNFG&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;+&lt;/span&gt;&lt;span style=&#34;color:#f5a97f&#34;&gt;0x04&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//NOTE: a CLOSED (true) switch will read LOW
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;.thumb_func&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;.global&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;_start&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#91d7e3&#34;&gt;_start:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	&lt;span style=&#34;color:#8aadf4&#34;&gt;MOVS&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;R3&lt;/span&gt;, &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#1
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;	&lt;span style=&#34;color:#8aadf4&#34;&gt;LSLS&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;R3&lt;/span&gt;, &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#ledPinOffset  //R3 is now LED mask (1 at led pos)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;  &lt;span style=&#34;color:#8aadf4&#34;&gt;MOVS&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;R4&lt;/span&gt;, &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#1  
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;	&lt;span style=&#34;color:#8aadf4&#34;&gt;LSLS&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;R4&lt;/span&gt;, &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#switchPinOffset //R4 is now switch mask (1 at switch pos)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//The DIRSET should have one for every LED and 0 for everys switch.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;  &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//The 0 is the default, but an explicit set will be safe. 
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#8aadf4&#34;&gt;LDR&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;R5&lt;/span&gt;, &lt;span style=&#34;color:#ed8796&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#eed49f&#34;&gt;portA_DIRSET&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#8aadf4&#34;&gt;STR&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;R3&lt;/span&gt;, [&lt;span style=&#34;color:#eed49f&#34;&gt;R5&lt;/span&gt;]   &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//move the 1s in for the LEDs
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;  &lt;span style=&#34;color:#8aadf4&#34;&gt;LDR&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;R5&lt;/span&gt;, &lt;span style=&#34;color:#ed8796&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#eed49f&#34;&gt;portA_DIRCLR&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#8aadf4&#34;&gt;STR&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;R4&lt;/span&gt;, [&lt;span style=&#34;color:#eed49f&#34;&gt;R5&lt;/span&gt;]   &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//clear all the switches
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#91d7e3&#34;&gt;setPullup:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//---- For using internal pullup only
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;  &lt;span style=&#34;color:#8aadf4&#34;&gt;LDR&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;R5&lt;/span&gt;, &lt;span style=&#34;color:#ed8796&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#eed49f&#34;&gt;switchPinCNFGOffset&lt;/span&gt; &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//pinConfig closest word location
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;  &lt;span style=&#34;color:#8aadf4&#34;&gt;LDR&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;R0&lt;/span&gt;, [&lt;span style=&#34;color:#eed49f&#34;&gt;R5&lt;/span&gt;] &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//load current settings into R0
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;  &lt;span style=&#34;color:#8aadf4&#34;&gt;MOVS&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;R1&lt;/span&gt;, &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#6 //create value for INEN 1 (bit 1) //set PULLEN 1 (bit 2)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;  &lt;span style=&#34;color:#8aadf4&#34;&gt;LSLS&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;R1&lt;/span&gt;, &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#24 //(8*(7-4)) //move it from 4 to 7
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;  &lt;span style=&#34;color:#8aadf4&#34;&gt;ORRS&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;R0&lt;/span&gt;, &lt;span style=&#34;color:#eed49f&#34;&gt;R1&lt;/span&gt; &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//apply mask
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;  &lt;span style=&#34;color:#8aadf4&#34;&gt;STR&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;R0&lt;/span&gt;, [&lt;span style=&#34;color:#eed49f&#34;&gt;R5&lt;/span&gt;] &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//put the updated word back into the config.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;  &lt;span style=&#34;color:#8aadf4&#34;&gt;LDR&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;R5&lt;/span&gt;, &lt;span style=&#34;color:#ed8796&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#eed49f&#34;&gt;portA_OUTSET&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#8aadf4&#34;&gt;STR&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;R4&lt;/span&gt;, [&lt;span style=&#34;color:#eed49f&#34;&gt;R5&lt;/span&gt;] &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//set the out of the switch high
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;  &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//--- END setting internal pullup
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//if remove pullup code
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;  &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//set R5 to hold portA_OUTSET here
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;  &lt;span style=&#34;color:#8aadf4&#34;&gt;LDR&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;R6&lt;/span&gt;, &lt;span style=&#34;color:#ed8796&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#eed49f&#34;&gt;portA_OUTCLR&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#8aadf4&#34;&gt;LDR&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;R7&lt;/span&gt;, &lt;span style=&#34;color:#ed8796&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#eed49f&#34;&gt;portA_IN&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#91d7e3&#34;&gt;loop:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//get the value of the IN register
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#8aadf4&#34;&gt;LDR&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;R0&lt;/span&gt;, [&lt;span style=&#34;color:#eed49f&#34;&gt;R7&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//OPTION 1
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//Isolate the switch reading 
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#8aadf4&#34;&gt;ANDS&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;R0&lt;/span&gt;, &lt;span style=&#34;color:#eed49f&#34;&gt;R4&lt;/span&gt; &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//should typically be 1, due to pullup resistor
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#8aadf4&#34;&gt;MOVS&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;R1&lt;/span&gt;, &lt;span style=&#34;color:#eed49f&#34;&gt;R0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#8aadf4&#34;&gt;EORS&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;R1&lt;/span&gt;, &lt;span style=&#34;color:#eed49f&#34;&gt;R4&lt;/span&gt; &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//R1 will 1 at the switch bit iff the read was 0
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#8aadf4&#34;&gt;LSLS&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;R0&lt;/span&gt;, &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#3  //move bit 7 (switch) to 10 (led)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#8aadf4&#34;&gt;LSLS&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;R1&lt;/span&gt;, &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#3  //move bit 7 (switch) to 10 (led)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//Sending 0s the to set and clear registers has no effect.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//The state of R0 always matches what should go to CLEAR
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//The state of R1 matches what should be in SET 
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#8aadf4&#34;&gt;STR&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;R0&lt;/span&gt;, [&lt;span style=&#34;color:#eed49f&#34;&gt;R6&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#8aadf4&#34;&gt;STR&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;R1&lt;/span&gt;, [&lt;span style=&#34;color:#eed49f&#34;&gt;R5&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#8aadf4&#34;&gt;B&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;loop&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;version-2&#34;&gt;Version 2&lt;/h3&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-asm&#34; data-lang=&#34;asm&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;.syntax&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;unified&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;.cpu&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;cortex-m0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;.fpu&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;softvfp&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#eed49f&#34;&gt;.thumb&lt;/span&gt;  
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#eed49f&#34;&gt;.section&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;.text.program_code&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;.equ&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;portA_address&lt;/span&gt;, &lt;span style=&#34;color:#f5a97f&#34;&gt;0x41004400&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;.equ&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;portA_DIRCLR&lt;/span&gt;, &lt;span style=&#34;color:#f5a97f&#34;&gt;0x41004400&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;+&lt;/span&gt;&lt;span style=&#34;color:#f5a97f&#34;&gt;0x04&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;.equ&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;portA_DIRSET&lt;/span&gt;, &lt;span style=&#34;color:#f5a97f&#34;&gt;0x41004400&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;+&lt;/span&gt;&lt;span style=&#34;color:#f5a97f&#34;&gt;0x08&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;.equ&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;portA_OUTCLR&lt;/span&gt;, &lt;span style=&#34;color:#f5a97f&#34;&gt;0x41004400&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;+&lt;/span&gt;&lt;span style=&#34;color:#f5a97f&#34;&gt;0x14&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;.equ&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;portA_OUTSET&lt;/span&gt;, &lt;span style=&#34;color:#f5a97f&#34;&gt;0x41004400&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;+&lt;/span&gt;&lt;span style=&#34;color:#f5a97f&#34;&gt;0x18&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//.equ portA_OUTTGL, 0x41004400+0x1C
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;.equ&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;portA_IN&lt;/span&gt;, &lt;span style=&#34;color:#f5a97f&#34;&gt;0x41004400&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;+&lt;/span&gt;&lt;span style=&#34;color:#f5a97f&#34;&gt;0x20&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;.equ&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;portA_WRCONFIG&lt;/span&gt;, &lt;span style=&#34;color:#f5a97f&#34;&gt;0x41004400&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;+&lt;/span&gt;&lt;span style=&#34;color:#f5a97f&#34;&gt;0x28&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;.equ&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;portA_PINCNFG&lt;/span&gt;, &lt;span style=&#34;color:#f5a97f&#34;&gt;0x41004400&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;+&lt;/span&gt;&lt;span style=&#34;color:#f5a97f&#34;&gt;0x40&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;.equ&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;ledPinOffset&lt;/span&gt;, &lt;span style=&#34;color:#f5a97f&#34;&gt;10&lt;/span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//PA10
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;.equ&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;switchPinOffset&lt;/span&gt;, &lt;span style=&#34;color:#f5a97f&#34;&gt;7&lt;/span&gt;  &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//PA07, 
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//NOTE: a CLOSED switch will read LOW
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//since pull a byte later, need the raw value to be a byte
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;.thumb_func&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;.global&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;_start&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#91d7e3&#34;&gt;_start:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#8aadf4&#34;&gt;MOVS&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;R4&lt;/span&gt;, &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#1 
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;  &lt;span style=&#34;color:#8aadf4&#34;&gt;LSLS&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;R3&lt;/span&gt;, &lt;span style=&#34;color:#eed49f&#34;&gt;R4&lt;/span&gt;, &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#ledPinOffset //R3 is now LED mask (1 at led pos)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;  &lt;span style=&#34;color:#8aadf4&#34;&gt;LSLS&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;R4&lt;/span&gt;, &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#switchPinOffset  //R4 is now switch mask (1 at switch pos)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//The DIRSET should have one for every LED and 0 for everys switch.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;  &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//The 0 is the default, but an explicit set will be safe. 
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#8aadf4&#34;&gt;LDR&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;R5&lt;/span&gt;, &lt;span style=&#34;color:#ed8796&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#eed49f&#34;&gt;portA_DIRSET&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#8aadf4&#34;&gt;STR&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;R3&lt;/span&gt;, [&lt;span style=&#34;color:#eed49f&#34;&gt;R5&lt;/span&gt;]   &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//move the 1s in for the LEDs
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;  &lt;span style=&#34;color:#8aadf4&#34;&gt;LDR&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;R5&lt;/span&gt;, &lt;span style=&#34;color:#ed8796&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#eed49f&#34;&gt;portA_DIRCLR&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#8aadf4&#34;&gt;STR&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;R4&lt;/span&gt;, [&lt;span style=&#34;color:#eed49f&#34;&gt;R5&lt;/span&gt;]   &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//clear all the switches
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#ed8796&#34;&gt;@&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;OPTION&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;1&lt;/span&gt;: &lt;span style=&#34;color:#eed49f&#34;&gt;Set&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;1&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;pin&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#ed8796&#34;&gt;@&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;MOVS&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;R0&lt;/span&gt;, &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#switchPinOffset  //put switch # into R0 
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;  &lt;span style=&#34;color:#ed8796&#34;&gt;@&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;PUSH&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;{&lt;/span&gt;&lt;span style=&#34;color:#eed49f&#34;&gt;R0-R3&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;}&lt;/span&gt; &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// stash in stack
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;  &lt;span style=&#34;color:#ed8796&#34;&gt;@&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;BL&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;setPullup&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#ed8796&#34;&gt;@&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;POP&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;{&lt;/span&gt;&lt;span style=&#34;color:#eed49f&#34;&gt;R0-R3&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;}&lt;/span&gt;  &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// restore
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#ed8796&#34;&gt;@&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;OPTION&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;2&lt;/span&gt;: &lt;span style=&#34;color:#eed49f&#34;&gt;Set&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;multiple&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;pins&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#8aadf4&#34;&gt;MOVS&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;R0&lt;/span&gt;, &lt;span style=&#34;color:#eed49f&#34;&gt;R4&lt;/span&gt;  &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//put switch mask into R0
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;  &lt;span style=&#34;color:#8aadf4&#34;&gt;PUSH&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;{&lt;/span&gt;&lt;span style=&#34;color:#eed49f&#34;&gt;R0-R3&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;}&lt;/span&gt; &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//stash in stack
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;  &lt;span style=&#34;color:#8aadf4&#34;&gt;BL&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;multiPinPullup&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#8aadf4&#34;&gt;POP&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;{&lt;/span&gt;&lt;span style=&#34;color:#eed49f&#34;&gt;R0-R3&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;}&lt;/span&gt;  &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//restore 
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#8aadf4&#34;&gt;LDR&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;R5&lt;/span&gt;, &lt;span style=&#34;color:#ed8796&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#eed49f&#34;&gt;portA_OUTSET&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#8aadf4&#34;&gt;LDR&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;R6&lt;/span&gt;, &lt;span style=&#34;color:#ed8796&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#eed49f&#34;&gt;portA_OUTCLR&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#8aadf4&#34;&gt;LDR&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;R7&lt;/span&gt;, &lt;span style=&#34;color:#ed8796&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#eed49f&#34;&gt;portA_IN&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#91d7e3&#34;&gt;loop:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//get the value of the IN register
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#8aadf4&#34;&gt;LDR&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;R0&lt;/span&gt;, [&lt;span style=&#34;color:#eed49f&#34;&gt;R7&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;				        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//TST the reading against the mask. 
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;                &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//R0 should read 1 at switch location as default
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;                &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//due to pullup resistor so if the AND result
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#8aadf4&#34;&gt;TST&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;R0&lt;/span&gt;, &lt;span style=&#34;color:#eed49f&#34;&gt;R4&lt;/span&gt;  &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//EQUALS 0 (no match), the switch is _closed_ 
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#8aadf4&#34;&gt;BEQ&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;ledOn&lt;/span&gt;   &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//so jump to on
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	&lt;span style=&#34;color:#91d7e3&#34;&gt;ledOff:&lt;/span&gt;  &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//default path
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#8aadf4&#34;&gt;STR&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;R3&lt;/span&gt;, [&lt;span style=&#34;color:#eed49f&#34;&gt;R6&lt;/span&gt;] &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//R3==ledMask, R6==portA_OUTCLR
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#8aadf4&#34;&gt;B&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;loop&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#91d7e3&#34;&gt;ledOn:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#8aadf4&#34;&gt;STR&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;R3&lt;/span&gt;, [&lt;span style=&#34;color:#eed49f&#34;&gt;R5&lt;/span&gt;] &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//R3==ledMask, R5==portA_OUTSET
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#8aadf4&#34;&gt;B&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;loop&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//end _start
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//Set R0 to contain the 32 pin mask of pins that should have pullups
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;.word&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;multiPinPullup&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;.thumb_func&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#91d7e3&#34;&gt;multiPinPullup:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//Go ahead and set the ups
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;  &lt;span style=&#34;color:#8aadf4&#34;&gt;LDR&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;R1&lt;/span&gt;, &lt;span style=&#34;color:#ed8796&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#eed49f&#34;&gt;portA_OUTSET&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#8aadf4&#34;&gt;STR&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;R0&lt;/span&gt;, [&lt;span style=&#34;color:#eed49f&#34;&gt;R1&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#8aadf4&#34;&gt;MOVS&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;R2&lt;/span&gt;, &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#1
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;  &lt;span style=&#34;color:#8aadf4&#34;&gt;MOVS&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;R3&lt;/span&gt;, &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#2
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;  &lt;span style=&#34;color:#8aadf4&#34;&gt;RORS&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;R2&lt;/span&gt;, &lt;span style=&#34;color:#eed49f&#34;&gt;R3&lt;/span&gt;  &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// Bit 30 -&amp;gt; 1 to enable PINCFG set
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;  &lt;span style=&#34;color:#8aadf4&#34;&gt;MOVS&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;R3&lt;/span&gt;, &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#6  // INEN 1 (bit 1) //set PULLEN 1 (bit 2)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;  &lt;span style=&#34;color:#8aadf4&#34;&gt;LSLS&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;R3&lt;/span&gt;, &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#16 // move up to 3rd byte
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;  &lt;span style=&#34;color:#8aadf4&#34;&gt;ORRS&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;R3&lt;/span&gt;, &lt;span style=&#34;color:#eed49f&#34;&gt;R2&lt;/span&gt;  &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// Add bit 30 to R3
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#8aadf4&#34;&gt;LDR&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;R2&lt;/span&gt;, &lt;span style=&#34;color:#ed8796&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#0xFFFF
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;  &lt;span style=&#34;color:#8aadf4&#34;&gt;TST&lt;/span&gt;  &lt;span style=&#34;color:#eed49f&#34;&gt;R0&lt;/span&gt;, &lt;span style=&#34;color:#eed49f&#34;&gt;R2&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#8aadf4&#34;&gt;BEQ&lt;/span&gt;  &lt;span style=&#34;color:#eed49f&#34;&gt;mpp_upperHalf&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#8aadf4&#34;&gt;MOVS&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;R1&lt;/span&gt;, &lt;span style=&#34;color:#eed49f&#34;&gt;R0&lt;/span&gt;  &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// copy R0 for editing
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;  &lt;span style=&#34;color:#8aadf4&#34;&gt;ANDS&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;R1&lt;/span&gt;, &lt;span style=&#34;color:#eed49f&#34;&gt;R2&lt;/span&gt;   &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//isolate bottom half
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;  &lt;span style=&#34;color:#8aadf4&#34;&gt;ORRS&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;R1&lt;/span&gt;, &lt;span style=&#34;color:#eed49f&#34;&gt;R3&lt;/span&gt;  &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// update R1 with settings 
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;  &lt;span style=&#34;color:#8aadf4&#34;&gt;LDR&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;R2&lt;/span&gt;, &lt;span style=&#34;color:#ed8796&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#eed49f&#34;&gt;portA_WRCONFIG&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#8aadf4&#34;&gt;STR&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;R1&lt;/span&gt;, [&lt;span style=&#34;color:#eed49f&#34;&gt;R2&lt;/span&gt;] &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// send WRCONFIG bottom half info
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#91d7e3&#34;&gt;mpp_upperHalf:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#8aadf4&#34;&gt;LDR&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;R1&lt;/span&gt;, &lt;span style=&#34;color:#ed8796&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#0xFFFF0000
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;  &lt;span style=&#34;color:#8aadf4&#34;&gt;TST&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;R0&lt;/span&gt;, &lt;span style=&#34;color:#eed49f&#34;&gt;R1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#8aadf4&#34;&gt;BEQ&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;mpp_exit&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#8aadf4&#34;&gt;LSRS&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;R0&lt;/span&gt;, &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#16 // isolate top half
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;  &lt;span style=&#34;color:#8aadf4&#34;&gt;ORRS&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;R0&lt;/span&gt;, &lt;span style=&#34;color:#eed49f&#34;&gt;R3&lt;/span&gt;  &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// add settings
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;  &lt;span style=&#34;color:#8aadf4&#34;&gt;LSLS&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;R1&lt;/span&gt;, &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#15 // make R1 0x80000000
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;  &lt;span style=&#34;color:#8aadf4&#34;&gt;ORRS&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;R0&lt;/span&gt;, &lt;span style=&#34;color:#eed49f&#34;&gt;R1&lt;/span&gt;  &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// Add top half flag in bit 31
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;  &lt;span style=&#34;color:#8aadf4&#34;&gt;LDR&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;R2&lt;/span&gt;, &lt;span style=&#34;color:#ed8796&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#eed49f&#34;&gt;portA_WRCONFIG&lt;/span&gt; &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//might be this value already. 
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;  &lt;span style=&#34;color:#8aadf4&#34;&gt;STR&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;R0&lt;/span&gt;, [&lt;span style=&#34;color:#eed49f&#34;&gt;R2&lt;/span&gt;] &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// send WRCONFIG top half info
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;  &lt;span style=&#34;color:#91d7e3&#34;&gt;mpp_exit:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#8aadf4&#34;&gt;BX&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;LR&lt;/span&gt;  
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;summary&#34;&gt;Summary&lt;/h2&gt;
&lt;p&gt;Choosing the smallest of the Arm family makes writing the assembly extra fidly. To the rescue&amp;hellip; switching to C and letting the compiler sort it out!  That better matches the AVR example anyway. I&amp;rsquo;m going to do same GDB/makefile tidy-up in prep.&lt;/p&gt;
</description>
    </item>
    
    
    
    <item>
      <title>Uhg, How do I post a blinking LED image again?</title>
      <link>https://whynotestflight.com/excuses/uhg-how-do-i-post-a-blinking-led-image-again/</link>
      <pubDate>Tue, 23 Apr 2024 00:00:00 +0000</pubDate>
      
      <guid>https://whynotestflight.com/excuses/uhg-how-do-i-post-a-blinking-led-image-again/</guid>
      <description>&lt;p&gt;Every time I have to look this up&amp;hellip; I have a longer page of notes to go through, but at least I can post the links.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Official docs: &lt;a href=&#34;https://ffmpeg.org/ffmpeg.html&#34;&gt;https://ffmpeg.org/ffmpeg.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://ffmpeg.org/ffmpeg.html#toc-Video-and-Audio-file-format-conversion&#34;&gt;https://ffmpeg.org/ffmpeg.html#toc-Video-and-Audio-file-format-conversion&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://ffmpeg.org/ffmpeg-formats.html#image2-1&#34;&gt;https://ffmpeg.org/ffmpeg-formats.html#image2-1&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;link-dump&#34;&gt;Link Dump&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&#34;https://stackoverflow.com/questions/42980663/ffmpeg-high-quality-animated-gif&#34;&gt;https://stackoverflow.com/questions/42980663/ffmpeg-high-quality-animated-gif&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&#34;https://stackoverflow.com/questions/3211595/renaming-files-in-a-folder-to-sequential-numbers&#34;&gt;https://stackoverflow.com/questions/3211595/renaming-files-in-a-folder-to-sequential-numbers&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&#34;https://stackoverflow.com/questions/3688870/create-animated-gif-from-a-set-of-jpeg-images&#34;&gt;https://stackoverflow.com/questions/3688870/create-animated-gif-from-a-set-of-jpeg-images&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&#34;https://superuser.com/questions/556029/how-do-i-convert-a-video-to-gif-using-ffmpeg-with-reasonable-quality/556031#556031&#34;&gt;https://superuser.com/questions/556029/how-do-i-convert-a-video-to-gif-using-ffmpeg-with-reasonable-quality/556031#556031&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&#34;http://blog.pkh.me/p/21-high-quality-gif-with-ffmpeg.html&#34;&gt;http://blog.pkh.me/p/21-high-quality-gif-with-ffmpeg.html&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&#34;https://cassidy.codes/blog/2017/04/25/ffmpeg-frames-to-gif-optimization/&#34;&gt;https://cassidy.codes/blog/2017/04/25/ffmpeg-frames-to-gif-optimization/&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&#34;https://mattj.io/posts/2021-02-27-create-animated-gif-and-webp-from-videos-using-ffmpeg/&#34;&gt;https://mattj.io/posts/2021-02-27-create-animated-gif-and-webp-from-videos-using-ffmpeg/&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&#34;https://gist.github.com/devadvance/f2ad3cfe38afe3eeef64c72c46692158&#34;&gt;https://gist.github.com/devadvance/f2ad3cfe38afe3eeef64c72c46692158&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&#34;https://www.paulirish.com/2021/video-stabilization-with-ffmpeg-and-vidstab/&#34;&gt;https://www.paulirish.com/2021/video-stabilization-with-ffmpeg-and-vidstab/&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&#34;https://onlinegiftools.com/analyze-gif&#34;&gt;https://onlinegiftools.com/analyze-gif&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&#34;https://www.baeldung.com/linux/convert-videos-gifs-ffmpeg&#34;&gt;https://www.baeldung.com/linux/convert-videos-gifs-ffmpeg&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&#34;https://shotstack.io/learn/convert-video-gif-ffmpeg/&#34;&gt;https://shotstack.io/learn/convert-video-gif-ffmpeg/&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&#34;https://ffmpeg.org/ffmpeg-filters.html#paletteuse&#34;&gt;https://ffmpeg.org/ffmpeg-filters.html#paletteuse&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;framerate&lt;/code&gt;: Set the frame rate for the video stream. It defaults to 25.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;loop&lt;/code&gt;: If set to 1, loop over the input. Default value is 0.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;start_number&lt;/code&gt;: Set the index of the file matched by the image file pattern to start to read from. Default value is 0.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;start_number_range&lt;/code&gt;: Set the index interval range to check when looking for the first image file in the sequence, starting from start_number. Default value is 5.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;video_size&lt;/code&gt;: Set the video size of the images to read. If not specified the video size is guessed from the first image file in the sequence&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;-r[:&amp;lt;stream_spec&amp;gt;] &amp;lt;rate&amp;gt;&lt;/code&gt;:  override input framerate/convert to given output framerate (Hz value, fraction or abbreviation)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;-vf &amp;lt;filter_graph&amp;gt;&lt;/code&gt;:  alias for -filter:v (apply filters to video streams)&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;get ffmpeg&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-shell&#34; data-lang=&#34;shell&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;brew install ffmpeg
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Use ffmpeg for creating a video from the images in the file sequence img-001.jpeg, img-002.jpeg, &amp;hellip;, assuming an input frame rate of 10 frames per second:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-shell&#34; data-lang=&#34;shell&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ffmpeg -framerate &lt;span style=&#34;color:#f5a97f&#34;&gt;10&lt;/span&gt; -i &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#39;img-%03d.jpeg&amp;#39;&lt;/span&gt; out.mkv
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;As above, but start by reading from a file with index 100 in the sequence:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-shell&#34; data-lang=&#34;shell&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ffmpeg -framerate &lt;span style=&#34;color:#f5a97f&#34;&gt;10&lt;/span&gt; -start_number &lt;span style=&#34;color:#f5a97f&#34;&gt;100&lt;/span&gt; -i &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#39;img-%03d.jpeg&amp;#39;&lt;/span&gt; out.mkv
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Read images matching the &amp;ldquo;*.png&amp;rdquo; glob pattern , that is all the files terminating with the &amp;ldquo;.png&amp;rdquo; suffix:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-shell&#34; data-lang=&#34;shell&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ffmpeg -framerate &lt;span style=&#34;color:#f5a97f&#34;&gt;10&lt;/span&gt; -pattern_type glob -i &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;*.png&amp;#34;&lt;/span&gt; out.mkv 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#-video_size 320x240&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-shell&#34; data-lang=&#34;shell&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## destination folder must already exist.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ffmpeg -i &lt;span style=&#34;color:#f4dbd6&#34;&gt;$filename&lt;/span&gt;.mov -r &lt;span style=&#34;color:#f5a97f&#34;&gt;1&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;$filename_frames&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;/&lt;/span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;$filename&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;%03d.png&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## edit frames...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ffmpeg -f image2 -i &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;$filename_frames&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;/&lt;/span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;$filename&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;%03d.png&amp;#34;&lt;/span&gt; -loop &lt;span style=&#34;color:#f5a97f&#34;&gt;0&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;$filename&lt;/span&gt;.gif
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-shell&#34; data-lang=&#34;shell&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ffmpeg -i IMG_1703.mov -r &lt;span style=&#34;color:#f5a97f&#34;&gt;12&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;all_frames2/switch_press%03d.png&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-shell&#34; data-lang=&#34;shell&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ffmpeg -i &lt;span style=&#34;color:#f4dbd6&#34;&gt;$filename&lt;/span&gt;.mov -r &lt;span style=&#34;color:#f5a97f&#34;&gt;1&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;$filename_frames&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;/&lt;/span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;$filename&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;%03d.png&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ffmpeg -f image2 -i &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;$filename_frames&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;/&lt;/span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;$filename&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;%03d.png&amp;#34;&lt;/span&gt; -loop &lt;span style=&#34;color:#f5a97f&#34;&gt;0&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;$filename&lt;/span&gt;.gif
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# Change these placeholders:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# * $INPUT_START_TIME - number of seconds in the input video to start from.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# * $LENGTH - number of seconds to convert from the input video.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# * $INPUT_FILENAME - path to the input video.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# * $OUTPUT_FPS - ouput frames per second. Start with `10`.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# * $OUTPUT_WIDTH - output width in pixels. Aspect ratio is maintained.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# * $NUMBER_OF_LOOPS - use `0` to loop forever, or a specific number of loops.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# * $OUTPUT_FILENAME - the name of the output animated GIF.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ffmpeg -ss &lt;span style=&#34;color:#f4dbd6&#34;&gt;$INPUT_START_TIME&lt;/span&gt; -t &lt;span style=&#34;color:#f4dbd6&#34;&gt;$LENGTH&lt;/span&gt; -i &lt;span style=&#34;color:#f4dbd6&#34;&gt;$INPUT_FILENAME&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;&lt;/span&gt;-vf &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;fps=&lt;/span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;$OUTPUT_FPS&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;,scale=&lt;/span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;$OUTPUT_WIDTH&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;:-1:flags=lanczos,split[s0][s1];[s0]palettegen[p];[s1][p]paletteuse&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;&lt;/span&gt;-loop &lt;span style=&#34;color:#f4dbd6&#34;&gt;$NUMBER_OF_LOOPS&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;$OUTPUT_FILENAME&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-shell&#34; data-lang=&#34;shell&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ffmpeg -f image2 -framerate &lt;span style=&#34;color:#f5a97f&#34;&gt;12&lt;/span&gt; -start_number &lt;span style=&#34;color:#f5a97f&#34;&gt;085&lt;/span&gt; -i these/switch_press%003d.png -vf &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;fps=12,scale=240:-1:flags=lanczos,split[s0][s1];[s0]palettegen[p];[s1][p]paletteuse&amp;#34;&lt;/span&gt; -loop &lt;span style=&#34;color:#f5a97f&#34;&gt;0&lt;/span&gt; touch_12fps.gif
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;num&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt;298; &lt;span style=&#34;color:#c6a0f6&#34;&gt;for&lt;/span&gt; i in *; &lt;span style=&#34;color:#c6a0f6&#34;&gt;do&lt;/span&gt; mv &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;$i&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;$(&lt;/span&gt;&lt;span style=&#34;color:#91d7e3&#34;&gt;printf&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#39;switch_press%003d&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;$num&lt;/span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;.&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;${&lt;/span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;i&lt;/span&gt;#*.&lt;span style=&#34;color:#a6da95&#34;&gt;}&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;((&lt;/span&gt;num++&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;))&lt;/span&gt;; &lt;span style=&#34;color:#c6a0f6&#34;&gt;done&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ffmpeg -f image2 -i &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;these5/switch_press%003d.png&amp;#34;&lt;/span&gt; -loop &lt;span style=&#34;color:#f5a97f&#34;&gt;0&lt;/span&gt; touchc.gif
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ffmpeg -f image2 -framerate &lt;span style=&#34;color:#f5a97f&#34;&gt;12&lt;/span&gt; -i these/switch_press%003d.png -vf &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;fps=10,scale=320:-1:flags=lanczos,split[s0][s1];[s0]palettegen[p];[s1][p]paletteuse&amp;#34;&lt;/span&gt; -loop &lt;span style=&#34;color:#f5a97f&#34;&gt;0&lt;/span&gt; toucha_12to10fps.gif
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ffmpeg -i IMG_1706.mov -vf &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;palettegen&amp;#34;&lt;/span&gt; palette.png
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ffmpeg -i IMG_1706.mov -loop &lt;span style=&#34;color:#f5a97f&#34;&gt;0&lt;/span&gt; -filter_complex &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;fps=10, scale=-1:240[s]; [s]split[a][b]; [a]palettegen[palette]; [b][palette]paletteuse&amp;#34;&lt;/span&gt; final_a.gif
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description>
    </item>
    
    
    
    <item>
      <title>It&#39;s ALIVE! (SAMD21E18A, Assembly, No SDK)</title>
      <link>https://whynotestflight.com/excuses/its-alive-samd21e18a-assembly-no-sdk/</link>
      <pubDate>Mon, 15 Apr 2024 00:00:00 +0000</pubDate>
      
      <guid>https://whynotestflight.com/excuses/its-alive-samd21e18a-assembly-no-sdk/</guid>
      <description>&lt;style&gt;
table.foo {
    width:90%
    margin:0px;
    padding:0px;
    line-height:22px;
    font-size:smaller;
    font-family:Arial, Verdana, Tahoma, Helvetica, sans-serif;
    font-weight:200;
    text-decoration:none;
    white-space:pre-wrap;
}
table.foo td {
  width:10%;
  margin: 5px;
}

table.foo th {
    font-family:Arial, Verdana, Tahoma, Helvetica, sans-serif;
    font-weight:200;
}

table.foo strong {
  font-weight:1200;
  
}

.take_away {
    color: #88AAEE;
}

.data {
    font-size:smaller;
}

h4.take_away {
    margin-bottom: 5px 
}

.odd td:nth-child(odd)  {
  /*border: 2px solid orange; */
   color: #88AAEE;
  margin-bottom: 1px;
}

table.odd {
    font-size:smaller;
}



&lt;/style&gt;
&lt;p&gt;Related Repo: &lt;a href=&#34;https://github.com/carlynorama/StrippedDownChipRosetta/tree/main/ARM/SAMD21E18/03_AssmeblyBlink&#34;&gt;https://github.com/carlynorama/StrippedDownChipRosetta/tree/main/ARM/SAMD21E18/03_AssmeblyBlink&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;blink_18fps.gif&#34; alt=&#34;Animated GIF of the blinking LED&#34;&gt;&lt;/p&gt;
&lt;h2 id=&#34;more-refs&#34;&gt;More Refs&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;
    
            
    YouTube:
            &lt;a href=&#34;https://www.youtube.com/playlist?list=PL5PHm2jkkXmi5CxxI7b3JCL1TWybTDtKq&#34;&gt;CMU Computer Architecture (18-447), Spring 2015&lt;/a&gt;
                by &lt;a href=&#34;https://www.youtube.com/@Carnegie%20Mellon%20Computer%20Architecture&#34;&gt;Carnegie Mellon Computer Architecture&lt;/a&gt;
        If one wants to go off in the weeds? Taught by Prof. Onur Mutlu&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
    
        
            
    YouTube:
    &lt;a href=&#34;https://www.youtube.com/watch?v=aT5XMOrid7Y&amp;amp;list=PLxfrSxK7P38X7XfG4X8Y9cdOURvC7ObMF&#34;&gt;Lecture 5: Memory Mapped I/O&lt;/a&gt;
             (8:22) as part of
            &lt;a href=&#34;https://www.youtube.com/playlist?list=PLxfrSxK7P38X7XfG4X8Y9cdOURvC7ObMF&#34;&gt;Short Lectures&lt;/a&gt;
                by &lt;a href=&#34;https://www.youtube.com/@Embedded%20Systems%20and%20Deep%20Learning&#34;&gt;Embedded Systems and Deep Learning&lt;/a&gt;
        Playlist for book by Yifeng Zhu&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://www.se.rit.edu/~llk/cmpe-240/lectures/Chapter_14_GPIO.pdf&#34;&gt;Chapter 14: GPIO&lt;/a&gt; PDF of slides from above video by Dr. Yifeng Zhu for his 2018 class at the University of Maine&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
    
            
    YouTube:
            &lt;a href=&#34;https://www.youtube.com/playlist?list=PLiRALtgGsxmYTF6ZqDSg4DRWDLGVer-Kb&#34;&gt;Raspberry Pi Pico Bare Metal Programming&lt;/a&gt;
                by &lt;a href=&#34;https://www.youtube.com/@Life%20with%20David&#34;&gt;Life with David&lt;/a&gt;
        I&amp;#39;ve only watched the first one but it looks excellent. Based on the RP2040&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;GitHub: The &lt;a href=&#34;https://github.com/micropython/micropython/tree/5114f2c1ea7c05fc7ab920299967595cfc5307de/ports/samd&#34;&gt;samd port folder&lt;/a&gt; (5114f2c) in the &lt;a href=&#34;https://github.com/micropython/micropython/&#34;&gt;micropython repo&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;finding-the-gpio-information-in-the-datasheet&#34;&gt;Finding the GPIO Information in the Datasheet&lt;/h2&gt;
&lt;p&gt;Still &lt;a href=&#34;https://ww1.microchip.com/downloads/aemDocuments/documents/MCU32/ProductDocuments/DataSheets/SAM-D21-DA1-Family-Data-Sheet-DS40001882H.pdf&#34;&gt;this one&lt;/a&gt;&lt;/p&gt;
&lt;h3 id=&#34;what-pin-do-we-care-about&#34;&gt;What Pin do we care about?&lt;/h3&gt;
&lt;h4 id=&#34;d13--pa10&#34; class=&#34;take_away&#34;&gt;D13 == PA10&lt;/h4&gt;
&lt;p&gt;We aren&amp;rsquo;t trying to figure out how to lay out a circuit, we&amp;rsquo;re trying to figure out how to talk to the circuit we have. The PyRuler like many arduino compatible boards has a built in LED on &amp;ldquo;pin 13&amp;rdquo;. That means NOTHING to the SAMD21E18A. Going to the &lt;a href=&#34;https://learn.adafruit.com/adafruit-trinket-m0-circuitpython-arduino/pinouts&#34;&gt;Adafruit docs on the Trinket M0&lt;/a&gt;, we can see that D13 matches to PA10.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;trinket.png&#34; alt=&#34;Trinket pinouts&#34;&gt;&lt;/p&gt;
&lt;h3 id=&#34;what-pins-does-the-chip-have&#34;&gt;What pins does the chip have?&lt;/h3&gt;
&lt;p&gt;When we write our code, what will be there to listen? What pins might have more than one purpose so if whe set a port up to do one thing it won&amp;rsquo;t do another?&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;5_5_pins.png&#34; alt=&#34;Pinouts for SAMD21E18A from Figure 5-5-1&#34;&gt;&lt;/p&gt;
&lt;p&gt;(Notice the number skipping compared the SAMD21J (5.1.1) , not all locations get a pin to the outside in this smaller package.)&lt;/p&gt;
&lt;h3 id=&#34;what-will-this-documentation-call-the-gpio-peripheral&#34;&gt;What will this documentation call the GPIO peripheral?&lt;/h3&gt;
&lt;h4 id=&#34;port&#34; class=&#34;take_away&#34;&gt;PORT&lt;/h4&gt;
&lt;p&gt;Chip documentation uses a lot of abbreviations,  steeped in history. Even though so many software packages call twiddling pins their GPIO library, an acronym, which you&amp;rsquo;d think would be perfect, don&amp;rsquo;t look for it in the datasheet.  If you didn&amp;rsquo;t know about the history, how might you find out?&lt;/p&gt;
&lt;p&gt;Section 6, Signal Descriptions List, gives us our list of acronyms for the type of electrical information the chip can take in and give out. Towards the end of the list we see &lt;strong&gt;&amp;ldquo;General Purpose I/O - PORT&amp;rdquo;&lt;/strong&gt; Gotcha.&lt;/p&gt;
&lt;h3 id=&#34;generally-speaking-where-will-these-values-be-in-memory&#34;&gt;Generally speaking where will these values be in memory?&lt;/h3&gt;
&lt;h4 id=&#34;lowest-value-0x40000000highest-value-0x42ffffff&#34; class=&#34;take_away&#34;&gt;lowest value: 0x40000000&lt;br&gt;highest value: 0x42FFFFFF&lt;/h4&gt;
&lt;p&gt;We know from Figure 9-1, the memory map (shown &lt;a href=&#34;https://whynotestflight.com/excuses/how-can-i-get-this-samd21e18-startup-code-a-little-sturdier/#product-mapping&#34;&gt;last post&lt;/a&gt;) where the peripherals will be in memory
memory map peripherals&lt;/p&gt;
&lt;h3 id=&#34;yeah-but-where-are-the-pins-in-there&#34;&gt;Yeah but where are the PINS in there?&lt;/h3&gt;
&lt;h4 id=&#34;port-0x41004400&#34; class=&#34;take_away&#34;&gt;PORT 0x41004400&lt;/h4&gt;
&lt;p&gt;Table 12-1. Peripherals Configuration Summary
Called PORT 0x41004400  (NOT GPIO) That puts it in the &lt;a href=&#34;https://onlinedocs.microchip.com/pr/GUID-2BBF0A73-A043-4A40-A6CA-0FF154E4BFFE-en-US-6/index.html?GUID-0244709C-F9ED-4F55-B4C2-B3ED9F77F41C&#34;&gt;AHB-APB Bridge B&lt;/a&gt; section. This is where the &amp;ldquo;memory map&amp;rdquo; happens.&lt;/p&gt;
&lt;h3 id=&#34;so-thats-where-the-pins-are-where-and-what-do-i-call-specifically-to-set-them&#34;&gt;So thats where the pins are, Where and what do I call specifically to set them?&lt;/h3&gt;
&lt;h4 id=&#34;pa-group-offset-0x00--0x41004400pb-group-offset-0x80--0x41004480&#34; class=&#34;take_away&#34;&gt;PA group offset 0x00 =&amp;gt; 0x41004400&lt;br&gt;PB group offset 0x80 =&amp;gt; 0x41004480&lt;/h4&gt;
&lt;p&gt;(from 23.6.2.2 Operation )&lt;/p&gt;
&lt;p&gt;Everything we need is in section &amp;ldquo;23. PORT - I/O Pin Controller&amp;rdquo;, especially how to interact with the Memory Mapped I/O. As mentioned in the video above (&lt;a href=&#34;https://www.youtube.com/watch?v=aT5XMOrid7Y&amp;amp;list=PLxfrSxK7P38X7XfG4X8Y9cdOURvC7ObMF&#34;&gt;Lecture 5: Memory Mapped I/O&lt;/a&gt;) there aren&amp;rsquo;t special port instructions at an assembly level on Arm chips, it&amp;rsquo;s all just memory instructions. Typically the chip manufacturers will provide special addresses to make certain operations faster.  We can find them in&lt;/p&gt;
&lt;p&gt;Table 23-7.&lt;/p&gt;
&lt;table class=&#34;odd&#34;&gt;
  &lt;thead&gt;
      &lt;tr&gt;
          &lt;th style=&#34;text-align: left&#34;&gt;Offset&lt;/th&gt;
          &lt;th style=&#34;text-align: left&#34;&gt;Name&lt;/th&gt;
          &lt;th style=&#34;text-align: left&#34;&gt;Acronym&lt;/th&gt;
          &lt;th style=&#34;text-align: left&#34;&gt;Usage&lt;/th&gt;
      &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
      &lt;tr&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;0x00&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;Data Direction Values&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;DIR&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;0 is input, 1 output&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;0x04&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;Data Direction Clear&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;DIRCLR&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;set to input with a 1 at bit, 0 no change&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;0x08&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;Data Direction Set&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;DIRSET&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;set to output with a 1 at bit, 0 no change&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;0x08&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;Data Direction Toggle&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;DIRTGL&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;toggled with a 1 at bit, 0 no change&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;0x10&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;Data Output Value&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;OUT&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;0 is low, 1 is high&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;0x14&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;Data Output Clear&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;OUTCLR&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;set to low with a 1 at bit, 0 no change&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;0x18&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;Data Output Set&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;OUTSET&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;set to high with a 1 at bit, 0 no change&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;0x1C&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;Data Output Toggle&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;OUTTGL&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;toggled with a 1 at bit, 0 no change&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;0x20&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;Data Input Value&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;IN&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;0 is a low reading, 1 is a high reading&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;0x24&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;Input Sampling Mode&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;CTRL&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;0 on demand sampling, 1 continuous sampling&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;0x28&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;Write Configuration&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;WRCONFIG&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;various meanings see 23.8.11&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;0x30&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;Peripheral Multiplexing&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;PMUX&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;see 23.8.12 and Sec. 7&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;0x40&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;Pin Configuration&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;PINCFG&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;various see 23.8.13, AND Table 23-2&lt;/td&gt;
      &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id=&#34;what-about-when-i-want-a-to-add-a-switch&#34;&gt;What about when I want a to add a switch?&lt;/h3&gt;
&lt;p&gt;Remember for the ATtiny45 I had to &lt;a href=&#34;https://whynotestflight.com/excuses/hello-led-on-an-avr-attiny45-in-c/&#34;&gt;set the pull up&lt;/a&gt;? Same for the SAMD21E18A. The configuration information lives in Table 23-2 (Pin Configurations Summary) and section 23.8.13 (PINCFG register details).&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;23_6_3_1_PinConfig.png&#34; alt=&#34;Screenshot of pinconfig summary from the datasheet&#34;&gt;&lt;/p&gt;
&lt;p&gt;See 23.8.13&lt;br&gt;
offset to pin settings == n*0x01 [n=0..31]&lt;/p&gt;
&lt;table class=&#34;foo&#34;&gt;
  &lt;thead&gt;
      &lt;tr&gt;
          &lt;th style=&#34;text-align: left&#34;&gt;7&lt;/th&gt;
          &lt;th style=&#34;text-align: left&#34;&gt;6&lt;/th&gt;
          &lt;th style=&#34;text-align: left&#34;&gt;5&lt;/th&gt;
          &lt;th style=&#34;text-align: left&#34;&gt;4&lt;/th&gt;
          &lt;th style=&#34;text-align: left&#34;&gt;3&lt;/th&gt;
          &lt;th style=&#34;text-align: left&#34;&gt;2&lt;/th&gt;
          &lt;th style=&#34;text-align: left&#34;&gt;1&lt;/th&gt;
          &lt;th style=&#34;text-align: left&#34;&gt;0&lt;/th&gt;
      &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
      &lt;tr&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;DRVSTR&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;PULLEN&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;INEN&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;PMUXEN&lt;/td&gt;
      &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;They&amp;rsquo;re a little tricky to use so lets do an example. Say I want a switch with logic low and a pull up resistor on PA05:&lt;/p&gt;
&lt;table class=&#34;odd&#34;&gt;
  &lt;thead&gt;
      &lt;tr&gt;
          &lt;th style=&#34;text-align: left&#34;&gt;Byte Address&lt;/th&gt;
          &lt;th style=&#34;text-align: left&#34;&gt;Name&lt;/th&gt;
          &lt;th style=&#34;text-align: left&#34;&gt;Value for Pin&lt;/th&gt;
          &lt;th style=&#34;text-align: left&#34;&gt;Byte Address Calc&lt;/th&gt;
          &lt;th style=&#34;text-align: left&#34;&gt;Which Bit&lt;/th&gt;
          &lt;th style=&#34;text-align: left&#34;&gt;Meaning&lt;/th&gt;
      &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
      &lt;tr&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;0x41004400&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;DIR&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;0&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;PORT + DIR&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;5&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;Pin 5 is an output&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;0x41004445&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;DPINCFG05.INEN&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;1&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;PORTA + PINCONFIG + pin settings&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;INEN (bit 1)&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;Turn on the input buffer&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;0x41004445&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;DPINCFG05.PULLEN&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;1&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;PORTA + PINCONFIG + pin settings&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;PULLEN (bit 2)&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;Use a pull&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;0x41004410&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;OUT&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;1&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;PORT + OUT&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;5&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;That pull should be a pull up&lt;/td&gt;
      &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id=&#34;delay-time&#34;&gt;Delay Time&lt;/h2&gt;
&lt;h4 id=&#34;gclk-0x40000c00default-1mhz-clock---osc8m8&#34; class=&#34;take_away&#34;&gt;GCLK 0x40000C00&lt;br&gt;Default: 1MHz clock - OSC8M/8&lt;/h4&gt;
&lt;p&gt;Another thing I did with the ATtiny45 was check the &lt;a href=&#34;https://whynotestflight.com/excuses/hello-led-on-an-avr-attiny45-in-c/#more-on-fuses--clock-settings&#34;&gt;clock settings&lt;/a&gt;. In Section 8.3.1, Starting of Clocks, the datasheet says - &amp;ldquo;the device will use a 1MHz clock. This clock is derived from the 8MHz Internal Oscillator (OSC8M), which is divided by eight.&amp;rdquo;  Since that matches how I left the the ATtiny project, I&amp;rsquo;ll leave this chip alone.&lt;/p&gt;
&lt;p&gt;Arm&amp;rsquo;s Cortex-M0+, the smallest of the family, offers more than one clock to it&amp;rsquo;s peripherals. That&amp;rsquo;s impressive. All of this is in Section 15 on GCLK, We&amp;rsquo;d have picked up from table 12-1 that all the offsets in this section are from GCLK 0x40000C00&lt;/p&gt;
&lt;p&gt;What we want is in 15.7 the register summary and the follow up detailed pages.&lt;/p&gt;
&lt;table class=&#34;odd&#34;&gt;
  &lt;thead&gt;
      &lt;tr&gt;
          &lt;th style=&#34;text-align: left&#34;&gt;Offset&lt;/th&gt;
          &lt;th style=&#34;text-align: left&#34;&gt;Name&lt;/th&gt;
          &lt;th style=&#34;text-align: left&#34;&gt;Acronym&lt;/th&gt;
          &lt;th style=&#34;text-align: left&#34;&gt;Usage&lt;/th&gt;
      &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
      &lt;tr&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;0x00&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;Control&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;CNTRL&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;Only bit 0, SWRST, software reset&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;0x01&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;Status&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;STATUS&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;Only bit 7, SYNCBUSY, Synchronization Busy Bus&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;0x02&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;Generic Clock Control&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;CLKCNTRL&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;WRTLOCK, CLKEN, GEN and ID&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;0x04&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;Generic Clock Generator Control&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;GENCNTRL&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;RUNSTDBY, DIVSEL, OE, OOV, IDC, GENEN, SRC, ID&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;0x08&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;Generic Clock Generator Division&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;GENDIV&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;0 is low, 1 is high&lt;/td&gt;
      &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;The key bits for inspecting that 1MHz clock:&lt;/p&gt;
&lt;p class=&#34;data&#34;&gt;GENCNTRL&lt;br&gt;
Bit 20 – DIVSEL
Bits 12:8 - SRC&lt;br&gt;
Bits 3:0 - ID&lt;/p&gt;
&lt;p class=&#34;data&#34;&gt;GENDIV&lt;br&gt;
Bits 23:8 – DIV
Bits 3:0 - ID&lt;/p&gt;
&lt;p&gt;Once I start loading code on the chip, I will use GDB to inspect the proper location.&lt;/p&gt;
&lt;h2 id=&#34;options-for-blinking-in-assembly&#34;&gt;Options for Blinking in Assembly&lt;/h2&gt;
&lt;p&gt;Assembly has different strategies than C. Try this  &lt;a href=&#34;https://www.youtube.com/watch?v=pgRuvOhZ3xM&amp;amp;list=PL2EF13wm-hWAlQe87UB2HV0SVhBXFpXbn&amp;amp;index=13&#34;&gt;fake-led blinking demo&lt;/a&gt; example first if you didn&amp;rsquo;t already.&lt;/p&gt;
&lt;p&gt;I have two strategies I want to show. Both of these behave as if we only had the one address to use, the Data Output Value. SLOOOOW. The code on chip will be faster.&lt;/p&gt;
&lt;h3 id=&#34;explicit-shifting-and-setting&#34;&gt;Explicit shifting and setting&lt;/h3&gt;
&lt;p&gt;&lt;a href=&#34;https://cpulator.01xz.net/?sys=arm-de1soc&amp;amp;loadasm=share/swuYBNv.s&#34;&gt;Example Link&lt;/a&gt;&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-asm&#34; data-lang=&#34;asm&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;.equ&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;led_reg_addr&lt;/span&gt;, &lt;span style=&#34;color:#f5a97f&#34;&gt;0xff200000&lt;/span&gt;  &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// some archs have separate read and write addr
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;.equ&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;onValue&lt;/span&gt;, &lt;span style=&#34;color:#f5a97f&#34;&gt;0x1&lt;/span&gt;     &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//will matter later because in real circuit 0 is frequently on
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;.equ&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;offValue&lt;/span&gt;, &lt;span style=&#34;color:#f5a97f&#34;&gt;0x0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;.equ&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;pinLocation&lt;/span&gt;, &lt;span style=&#34;color:#f5a97f&#34;&gt;3&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;.equ&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;delayTime&lt;/span&gt;, &lt;span style=&#34;color:#f5a97f&#34;&gt;3&lt;/span&gt;  &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// low number because I only step through on emulator
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;.global&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;_start&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#91d7e3&#34;&gt;_start:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	&lt;span style=&#34;color:#91d7e3&#34;&gt;loop:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;		&lt;span style=&#34;color:#8aadf4&#34;&gt;MOV&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;R3&lt;/span&gt;, &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#delayTime
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;		&lt;span style=&#34;color:#8aadf4&#34;&gt;MOV&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;R1&lt;/span&gt;, &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#onValue
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;		&lt;span style=&#34;color:#8aadf4&#34;&gt;LSL&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;R1&lt;/span&gt;, &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#pinLocation  //create the value
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;		&lt;span style=&#34;color:#8aadf4&#34;&gt;LDR&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;R0&lt;/span&gt;, &lt;span style=&#34;color:#ed8796&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#eed49f&#34;&gt;led_reg_addr&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;		&lt;span style=&#34;color:#8aadf4&#34;&gt;STR&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;R1&lt;/span&gt;, [&lt;span style=&#34;color:#eed49f&#34;&gt;R0&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;		&lt;span style=&#34;color:#8aadf4&#34;&gt;BL&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;delay&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;		&lt;span style=&#34;color:#8aadf4&#34;&gt;MOV&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;R3&lt;/span&gt;, &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#delayTime
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;		&lt;span style=&#34;color:#8aadf4&#34;&gt;MOV&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;R1&lt;/span&gt;, &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#offValue
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;		&lt;span style=&#34;color:#8aadf4&#34;&gt;LSL&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;R1&lt;/span&gt;, &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#pinLocation
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;		&lt;span style=&#34;color:#8aadf4&#34;&gt;LDR&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;R0&lt;/span&gt;, &lt;span style=&#34;color:#ed8796&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#eed49f&#34;&gt;LED&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;		&lt;span style=&#34;color:#8aadf4&#34;&gt;STR&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;R1&lt;/span&gt;, [&lt;span style=&#34;color:#eed49f&#34;&gt;R0&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;		&lt;span style=&#34;color:#8aadf4&#34;&gt;BL&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;delay&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	&lt;span style=&#34;color:#8aadf4&#34;&gt;BAL&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;loop&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#91d7e3&#34;&gt;delay:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	&lt;span style=&#34;color:#8aadf4&#34;&gt;SUBS&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;R3&lt;/span&gt;, &lt;span style=&#34;color:#eed49f&#34;&gt;R3&lt;/span&gt;, &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#1
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;	&lt;span style=&#34;color:#8aadf4&#34;&gt;BNE&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;delay&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	&lt;span style=&#34;color:#8aadf4&#34;&gt;BX&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;LR&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;xor-toggle&#34;&gt;XOR Toggle&lt;/h3&gt;
&lt;p&gt;&lt;a href=&#34;https://cpulator.01xz.net/?sys=arm-de1soc&amp;amp;loadasm=share/sIGWRT8.s&#34;&gt;Example Link&lt;/a&gt;&lt;br&gt;
&lt;a href=&#34;https://electronics.stackexchange.com/questions/70665/fastest-way-to-toggle-a-bit-in-asm&#34;&gt;discussion&lt;/a&gt;&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-asm&#34; data-lang=&#34;asm&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;.equ&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;led_add_reg&lt;/span&gt;, &lt;span style=&#34;color:#f5a97f&#34;&gt;0xff200000&lt;/span&gt; &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//some archs have a 
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;							 &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//different read and write 
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;							 &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//address
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;.equ&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;maskValue&lt;/span&gt;, &lt;span style=&#34;color:#f5a97f&#34;&gt;8&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;.equ&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;delayTime&lt;/span&gt;, &lt;span style=&#34;color:#f5a97f&#34;&gt;3&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;.global&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;_start&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#91d7e3&#34;&gt;_start:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	&lt;span style=&#34;color:#8aadf4&#34;&gt;ldr&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;R5&lt;/span&gt;, &lt;span style=&#34;color:#ed8796&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#eed49f&#34;&gt;led_add_reg&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	&lt;span style=&#34;color:#8aadf4&#34;&gt;mov&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;R6&lt;/span&gt;, &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#maskValue
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;	
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	&lt;span style=&#34;color:#91d7e3&#34;&gt;loop:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;		&lt;span style=&#34;color:#8aadf4&#34;&gt;LDR&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;R4&lt;/span&gt;, [&lt;span style=&#34;color:#eed49f&#34;&gt;R5&lt;/span&gt;]  &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//if no one else will change the port or memory register (R4)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;                      &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//and have no other reason to check port, potentially 
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;                      &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//could skip the read and go with a desired initial value
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;                      &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//set before the loop and not do a full reload here. (just xor)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;		&lt;span style=&#34;color:#8aadf4&#34;&gt;EORS&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;R4&lt;/span&gt;, &lt;span style=&#34;color:#eed49f&#34;&gt;R6&lt;/span&gt; &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//XOR
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;		&lt;span style=&#34;color:#8aadf4&#34;&gt;STR&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;R4&lt;/span&gt;, [&lt;span style=&#34;color:#eed49f&#34;&gt;R5&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;		&lt;span style=&#34;color:#8aadf4&#34;&gt;LDR&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;R3&lt;/span&gt;, &lt;span style=&#34;color:#ed8796&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#eed49f&#34;&gt;delayTime&lt;/span&gt; &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//instead of mov for future value
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;		&lt;span style=&#34;color:#8aadf4&#34;&gt;BL&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;delay&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;		&lt;span style=&#34;color:#8aadf4&#34;&gt;B&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;loop&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#91d7e3&#34;&gt;delay:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	&lt;span style=&#34;color:#8aadf4&#34;&gt;SUBS&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;R3&lt;/span&gt;, &lt;span style=&#34;color:#eed49f&#34;&gt;R3&lt;/span&gt;, &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#1
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;	&lt;span style=&#34;color:#8aadf4&#34;&gt;BNE&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;delay&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	&lt;span style=&#34;color:#8aadf4&#34;&gt;BX&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;LR&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;now-try-it-for-real&#34;&gt;Now try it for real!&lt;/h2&gt;
&lt;p&gt;Finally! Whew.&lt;/p&gt;
&lt;p&gt;Only one file has changed. The whole project reduces to an 11kb elf file.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-asm&#34; data-lang=&#34;asm&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;.syntax&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;unified&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;.cpu&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;cortex-m0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;.fpu&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;softvfp&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#eed49f&#34;&gt;.thumb&lt;/span&gt;  
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#eed49f&#34;&gt;.section&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;.text.program_code&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;.equ&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;portA_address&lt;/span&gt;, &lt;span style=&#34;color:#f5a97f&#34;&gt;0x41004400&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;.equ&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;portA_DIRSET&lt;/span&gt;, &lt;span style=&#34;color:#f5a97f&#34;&gt;0x41004400&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;+&lt;/span&gt;&lt;span style=&#34;color:#f5a97f&#34;&gt;0x08&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;.equ&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;portA_OUTTGL&lt;/span&gt;, &lt;span style=&#34;color:#f5a97f&#34;&gt;0x41004400&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;+&lt;/span&gt;&lt;span style=&#34;color:#f5a97f&#34;&gt;0x1C&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;.equ&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;delayTime&lt;/span&gt;, &lt;span style=&#34;color:#f5a97f&#34;&gt;50000&lt;/span&gt;     &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//same clock speed as avr, so same value
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;.equ&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;pinOffset&lt;/span&gt;, &lt;span style=&#34;color:#f5a97f&#34;&gt;10&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;.thumb_func&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;.global&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;_start&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#91d7e3&#34;&gt;_start:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	&lt;span style=&#34;color:#8aadf4&#34;&gt;MOVS&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;R4&lt;/span&gt;, &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#1
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;	&lt;span style=&#34;color:#8aadf4&#34;&gt;LSLS&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;R4&lt;/span&gt;, &lt;span style=&#34;color:#eed49f&#34;&gt;R4&lt;/span&gt;, &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#pinOffset  //R4 now contains the 1 at the pin offset bit. 
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;                           &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//It should stay that way for the rest of the program
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//set the output pins
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;  &lt;span style=&#34;color:#8aadf4&#34;&gt;LDR&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;R5&lt;/span&gt;, &lt;span style=&#34;color:#ed8796&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#eed49f&#34;&gt;portA_DIRSET&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#8aadf4&#34;&gt;STR&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;R4&lt;/span&gt;, [&lt;span style=&#34;color:#eed49f&#34;&gt;R5&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#8aadf4&#34;&gt;LDR&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;R5&lt;/span&gt;, &lt;span style=&#34;color:#ed8796&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#eed49f&#34;&gt;portA_OUTTGL&lt;/span&gt;  &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//R5 now points to the toggle-address
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;                          &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//It should stay that way for the rest of the program
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#91d7e3&#34;&gt;loop:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#8aadf4&#34;&gt;STR&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;R4&lt;/span&gt;, [&lt;span style=&#34;color:#eed49f&#34;&gt;R5&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#8aadf4&#34;&gt;LDR&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;R3&lt;/span&gt;, &lt;span style=&#34;color:#ed8796&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#eed49f&#34;&gt;delayTime&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#8aadf4&#34;&gt;BL&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;delay&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#8aadf4&#34;&gt;B&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;loop&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;.thumb_func&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#91d7e3&#34;&gt;delay:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	&lt;span style=&#34;color:#8aadf4&#34;&gt;SUBS&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;R3&lt;/span&gt;, &lt;span style=&#34;color:#eed49f&#34;&gt;R3&lt;/span&gt;, &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#1
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;	&lt;span style=&#34;color:#8aadf4&#34;&gt;BNE&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;delay&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	&lt;span style=&#34;color:#8aadf4&#34;&gt;BX&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;LR&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;summary&#34;&gt;Summary&lt;/h2&gt;
&lt;p&gt;Now was that so hard?&lt;/p&gt;
</description>
    </item>
    
    
    
    <item>
      <title>(how can I get an aside?)</title>
      <link>https://whynotestflight.com/excuses/how-can-i-get-an-aside/</link>
      <pubDate>Fri, 12 Apr 2024 00:00:00 +0000</pubDate>
      
      <guid>https://whynotestflight.com/excuses/how-can-i-get-an-aside/</guid>
      <description>&lt;p&gt;I&amp;rsquo;ve been avoiding using hugo shortcodes as much as possible because I&amp;rsquo;m not committed to always using hugo.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;But since if I switch I will already have things to find and swap&amp;hellip;&lt;/li&gt;
&lt;li&gt;And it&amp;rsquo;s easier than learning &lt;a href=&#34;https://asciidoc.org&#34;&gt;asciidoc&lt;/a&gt; right now&amp;hellip;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;references&#34;&gt;References:&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;hugo doc pages:
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://gohugo.io/templates/shortcode-templates/&#34;&gt;https://gohugo.io/templates/shortcode-templates/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://gohugo.io/content-management/shortcodes/&#34;&gt;https://gohugo.io/content-management/shortcodes/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;github search: &lt;code&gt;path:shortcodes path:aside&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-ruby&#34; data-lang=&#34;ruby&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{{&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;-&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;$type&lt;/span&gt; :&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; default &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;note&amp;#34;&lt;/span&gt; (&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;.&lt;/span&gt;Get &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;type&amp;#34;&lt;/span&gt;) &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;-&lt;/span&gt;}}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;lt;&lt;/span&gt;aside class&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;DocsMarkdown--aside&amp;#34;&lt;/span&gt; role&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;note&amp;#34;&lt;/span&gt; data&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;-&lt;/span&gt;type&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;{{ $type }}&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  {{&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;-&lt;/span&gt; with &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;.&lt;/span&gt;Get &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;header&amp;#34;&lt;/span&gt; }}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;lt;&lt;/span&gt;div class&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;DocsMarkdown--aside-header&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;gt;&lt;/span&gt;{{&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;-&lt;/span&gt; safeHTML &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;.&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;-&lt;/span&gt;}}&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&#34;color:#8bd5ca&#34;&gt;/div&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8bd5ca&#34;&gt;  {{- end -}}
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8bd5ca&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8bd5ca&#34;&gt;  {{- .Inner | .Page.RenderString (dict &amp;#34;display&amp;#34; &amp;#34;block&amp;#34;) -}}
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8bd5ca&#34;&gt;&amp;lt;/&lt;/span&gt;aside&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;via &lt;a href=&#34;https://github.com/cloudflare/cloudflare-docs/blob/39138bdf91113cad9fd4f56f671e933849e71a18/layouts/shortcodes/Aside.html#L4&#34;&gt;CloudFlare&lt;/a&gt;&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-ruby&#34; data-lang=&#34;ruby&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{{&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;/*&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#eed49f&#34;&gt;Asides&lt;/span&gt; show up as a colored box&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;.&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;Most&lt;/span&gt; things (headings, figures, iframes etc&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;.&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;can be placed inside a box &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;and&lt;/span&gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;display&lt;/span&gt; well, but make sure to check the final result
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;especially on mobile&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; notice&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;/&lt;/span&gt;success&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;/&lt;/span&gt;warning
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;will give blue&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;/&lt;/span&gt;green&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;/&lt;/span&gt;red box
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;*/&lt;/span&gt;}}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{{ &lt;span style=&#34;color:#f4dbd6&#34;&gt;$_hugo_config&lt;/span&gt; :&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;`{ &amp;#34;version&amp;#34;: 1 }`&lt;/span&gt; }}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{{&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;-&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;$class&lt;/span&gt; :&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;.&lt;/span&gt;Get &lt;span style=&#34;color:#f5a97f&#34;&gt;0&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;|&lt;/span&gt; default &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;notice&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;-&lt;/span&gt;}}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{{&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;-&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;$markdown&lt;/span&gt; :&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;.&lt;/span&gt;Inner &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;|&lt;/span&gt; markdownify &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;-&lt;/span&gt;}}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;lt;&lt;/span&gt;aside class&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;{{ $class }}&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  {{ &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;not&lt;/span&gt; ( findRE &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&amp;lt;[h|p][^&amp;gt;]*&amp;gt;&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;$markdown&lt;/span&gt; ) }}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&#34;color:#91d7e3&#34;&gt;p&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;gt;&lt;/span&gt;{{ &lt;span style=&#34;color:#f4dbd6&#34;&gt;$markdown&lt;/span&gt; }}&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&#34;color:#8bd5ca&#34;&gt;/p&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8bd5ca&#34;&gt;  {{ else }}
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8bd5ca&#34;&gt;    {{ $markdown }}
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8bd5ca&#34;&gt;  {{ end }}
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8bd5ca&#34;&gt;&amp;lt;/&lt;/span&gt;aside&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;via &lt;a href=&#34;https://github.com/looeee/discoverthreejs-site/blob/7bbaf74cb09ed84941db3b3322604fd9c61eb99b/layouts/shortcodes/aside.html#L4&#34;&gt;discoverthree-js&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;But what I really want to start is just something like:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-ruby&#34; data-lang=&#34;ruby&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;lt;&lt;/span&gt;aside class&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;irt-aside&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  {{ &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;.&lt;/span&gt;Inner &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;|&lt;/span&gt; markdownify }}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&#34;color:#8bd5ca&#34;&gt;/aside&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;via &lt;a href=&#34;https://github.com/YOWCT/internal-red-tape-reduction-report/tree/884a5cf6546d691ed498923dfdb7f50ed1e828ad/layouts/shortcodes&#34;&gt;Ottowa civic tech&lt;/a&gt; (&lt;a href=&#34;https://github.com/YOWCT/internal-red-tape-reduction-report/blob/884a5cf6546d691ed498923dfdb7f50ed1e828ad/static/css/styles.css&#34;&gt;their css&lt;/a&gt;)&lt;/p&gt;
&lt;p&gt;Test of {{% aside %}} some multiline content with mark down  {{% /aside %}}:&lt;/p&gt;
&lt;aside&gt;
    is &lt;em&gt;this&lt;/em&gt; in an &lt;strong&gt;aside&lt;/strong&gt; tag?
&lt;/aside&gt;
&lt;p&gt;It was!&lt;/p&gt;
&lt;p&gt;But I have no styling for an aside tag.&lt;/p&gt;
&lt;p&gt;There are fancier ways to&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://discourse.gohugo.io/t/use-conditional-for-css-style-with-shortcode/26786/2&#34;&gt;conditionally add css&lt;/a&gt; depending on shortcodes,&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://www.banjocode.com/post/hugo/custom-css&#34;&gt;use the config file&lt;/a&gt; to make a custom list of css to include and update the head.html template&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Or maybe your theme, like the one I use (&lt;a href=&#34;https://github.com/LukasJoswiak/etch/&#34;&gt;etch&lt;/a&gt;), already gathers resources from the assets folder and you can replace the head.html partial&lt;/p&gt;
&lt;p&gt;Relevant section of original file:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-ruby&#34; data-lang=&#34;ruby&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    {{ &lt;span style=&#34;color:#f4dbd6&#34;&gt;$resources&lt;/span&gt; :&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; slice &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;-&lt;/span&gt;}}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    {{ &lt;span style=&#34;color:#f4dbd6&#34;&gt;$resources&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;$resources&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;|&lt;/span&gt; append (resources&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;.&lt;/span&gt;Get &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;css/main.css&amp;#34;&lt;/span&gt;) &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;-&lt;/span&gt;}}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    {{ &lt;span style=&#34;color:#f4dbd6&#34;&gt;$resources&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;$resources&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;|&lt;/span&gt; append (resources&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;.&lt;/span&gt;Get &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;css/min770px.css&amp;#34;&lt;/span&gt;) &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;-&lt;/span&gt;}}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    {{ &lt;span style=&#34;color:#f4dbd6&#34;&gt;$dark&lt;/span&gt; :&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;.&lt;/span&gt;Site&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;.&lt;/span&gt;Params&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;.&lt;/span&gt;dark &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;|&lt;/span&gt; default &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;auto&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;-&lt;/span&gt;}}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    {{ &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;not&lt;/span&gt; (eq &lt;span style=&#34;color:#f4dbd6&#34;&gt;$dark&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;off&amp;#34;&lt;/span&gt;) &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;-&lt;/span&gt;}}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        {{ &lt;span style=&#34;color:#f4dbd6&#34;&gt;$resources&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;$resources&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;|&lt;/span&gt; append (resources&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;.&lt;/span&gt;Get &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;css/dark.css&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;|&lt;/span&gt; resources&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;.&lt;/span&gt;ExecuteAsTemplate &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;dark.css&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;.&lt;/span&gt;) &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;-&lt;/span&gt;}}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    {{ &lt;span style=&#34;color:#c6a0f6&#34;&gt;end&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;-&lt;/span&gt;}}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    {{ &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;.&lt;/span&gt;Site&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;.&lt;/span&gt;Params&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;.&lt;/span&gt;highlight &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;-&lt;/span&gt;}}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        {{ &lt;span style=&#34;color:#f4dbd6&#34;&gt;$resources&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;$resources&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;|&lt;/span&gt; append (resources&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;.&lt;/span&gt;Get &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;css/syntax.css&amp;#34;&lt;/span&gt;) &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;-&lt;/span&gt;}}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    {{ &lt;span style=&#34;color:#c6a0f6&#34;&gt;end&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;-&lt;/span&gt;}}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    {{ &lt;span style=&#34;color:#f4dbd6&#34;&gt;$resources&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;$resources&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;|&lt;/span&gt; append (resources&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;.&lt;/span&gt;Get &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;css/aside.css&amp;#34;&lt;/span&gt;) &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;-&lt;/span&gt;}}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    {{ &lt;span style=&#34;color:#f4dbd6&#34;&gt;$css&lt;/span&gt; :&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;$resources&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;|&lt;/span&gt; resources&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;.&lt;/span&gt;Concat &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;css/style.css&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;|&lt;/span&gt; minify }}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    {{ &lt;span style=&#34;color:#91d7e3&#34;&gt;printf&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;`&amp;lt;link rel=&amp;#34;stylesheet&amp;#34; href=&amp;#34;%s&amp;#34;&amp;gt;`&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;$css&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;.&lt;/span&gt;RelPermalink &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;|&lt;/span&gt; safeHTML }}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;So I moved a copy of the head.html to my local partials folder and right above the call to concat and minify added:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-ruby&#34; data-lang=&#34;ruby&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    {{ &lt;span style=&#34;color:#f4dbd6&#34;&gt;$resources&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;$resources&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;|&lt;/span&gt; append (resources&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;.&lt;/span&gt;Get &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;css/aside.css&amp;#34;&lt;/span&gt;) &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;-&lt;/span&gt;}}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;If you&amp;rsquo;ve already customized your main css, consider just throwing the new aside spec in there. Fewer changed files to track after an update. I don&amp;rsquo;t think the theme I chose is getting updates anymore, so I&amp;rsquo;m not worried about that.&lt;/p&gt;
&lt;p&gt;I don&amp;rsquo;t really have time to swap in CSS brain so for now I mostly cribbed off of this theme&amp;rsquo;s code fence CSS.  Unlike the example I did not add a class to my shortcode partial.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-css&#34; data-lang=&#34;css&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;main&lt;/span&gt;#&lt;span style=&#34;color:#f5a97f&#34;&gt;content&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;aside&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;/* VSCode auto completed this, sure! */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;font-family&lt;/span&gt;: system-ui, &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;-&lt;/span&gt;apple-system, 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    BlinkMacSystemFont, &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#39;Segoe UI&amp;#39;&lt;/span&gt;, Roboto, Oxygen, Ubuntu, 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    Cantarell, &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#39;Open Sans&amp;#39;&lt;/span&gt;, &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#39;Helvetica Neue&amp;#39;&lt;/span&gt;, &lt;span style=&#34;color:#f5a97f&#34;&gt;sans-serif&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;main&lt;/span&gt;#&lt;span style=&#34;color:#f5a97f&#34;&gt;content&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;aside&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;font-size&lt;/span&gt;: &lt;span style=&#34;color:#f5a97f&#34;&gt;0.96&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;em&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;padding&lt;/span&gt;: &lt;span style=&#34;color:#f5a97f&#34;&gt;0&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;5&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;px&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;main&lt;/span&gt;#&lt;span style=&#34;color:#f5a97f&#34;&gt;content&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;aside&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;display&lt;/span&gt;: &lt;span style=&#34;color:#f5a97f&#34;&gt;block&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;overflow-x&lt;/span&gt;: &lt;span style=&#34;color:#f5a97f&#34;&gt;auto&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;/*font-size: 14px;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;    font-size: 1.4rem;*/&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;margin&lt;/span&gt;: &lt;span style=&#34;color:#f5a97f&#34;&gt;0&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;px&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;20&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;px&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;padding&lt;/span&gt;: &lt;span style=&#34;color:#f5a97f&#34;&gt;1.5&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;rem&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;1.5&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;rem&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;/*line-height: 1.4;*/&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;border&lt;/span&gt;: &lt;span style=&#34;color:#f5a97f&#34;&gt;1&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;px&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;solid&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;#b1b1b1&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;border-radius&lt;/span&gt;: &lt;span style=&#34;color:#f5a97f&#34;&gt;1&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;px&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Not quite ready for production, but progress.&lt;/p&gt;
</description>
    </item>
    
    
    
    <item>
      <title>(how did my hugo public folder get to be a mess?)</title>
      <link>https://whynotestflight.com/excuses/how-did-my-hugo-public-folder-get-to-be-a-mess/</link>
      <pubDate>Fri, 12 Apr 2024 00:00:00 +0000</pubDate>
      
      <guid>https://whynotestflight.com/excuses/how-did-my-hugo-public-folder-get-to-be-a-mess/</guid>
      <description>&lt;p&gt;I&amp;rsquo;m thinking changing folder names while &lt;code&gt;hugo serve -D&lt;/code&gt; is running isn&amp;rsquo;t such a good idea? I somehow ended up with a public folder that was a mess. With multiple folders that clearly were iterations of names I was work-shopping. If I had thought that through, oh course it would do that.&lt;/p&gt;
&lt;p&gt;And since I never looked, my rsync script was uploading huge amounts that it would never delete.&lt;/p&gt;
&lt;p&gt;I did two things to fix it&lt;/p&gt;
&lt;h2 id=&#34;1---cleaned-the-public-folder&#34;&gt;1 - Cleaned the public folder&lt;/h2&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-zsh&#34; data-lang=&#34;zsh&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;hugo --cleanDestinationDir
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;2---updated-my-upload-script&#34;&gt;2 - Updated my upload script&lt;/h2&gt;
&lt;p&gt;The original line excluded &lt;code&gt;.DS_Store&lt;/code&gt; but nothing else. Never deleted because what if I wanted to put non-hugo items up there?.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;rsync -zaP --exclude&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#39;.DS_Store&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;$SOURCE&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;$DESTINATION&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The new one, shown in context below, deletes everything that isn&amp;rsquo;t in the local public folder, but has an exceptions file. If the destination is space restrained, the slower exclude-before might be a better fit.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://rsync.samba.org&#34;&gt;rsync utility home&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://download.samba.org/pub/rsync/rsync.html&#34;&gt;rsync man page&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://rsync.samba.org/examples.html&#34;&gt;https://rsync.samba.org/examples.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://rsync.samba.org/resources.html&#34;&gt;https://rsync.samba.org/resources.html&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;SOURCE&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;$HUGO_ROOT&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;/public/&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;DESTINATION&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;$USER&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;@&lt;/span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;$HOST&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;:/home/&lt;/span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;$USER&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;/&lt;/span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;$SITENAME&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#echo &amp;#34;#rsync -zaP $SOURCE $DESTINATION&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# z: compress&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# a: archive mode (preserve permissions)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# P: show progress, keep partial (I watch every time)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;rsync -zaP --delete --exclude&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#39;.DS_Store&amp;#39;&lt;/span&gt; --exclude-from&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#39;exclude-rsync.txt&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;$SOURCE&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;$DESTINATION&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;example-exceptions-file&#34;&gt;example exceptions file:&lt;/h2&gt;
&lt;p&gt;the difference between dir/* and dir, is that the first refers to the contents and the later the directory itself as well.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-txt&#34; data-lang=&#34;txt&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;some_special_file.txt
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;pre* 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;dir1/*
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;dir
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Might have things like&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-txt&#34; data-lang=&#34;txt&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;favi*
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;robots.txt
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;.well-known
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;note-some-things-you-might-manually-add-can-be-done-via-hugo-instead-of-this-file&#34;&gt;Note: some things you might manually add can be done via hugo instead of this file&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;via the static folder - i.e. &lt;a href=&#34;https://stackoverflow.com/questions/42043648/where-do-i-put-my-favicon-with-hugo&#34;&gt;favicon&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;or configuration - i.e. &lt;a href=&#34;https://gohugo.io/templates/robots/&#34;&gt;robots.txt&lt;/a&gt; (&lt;a href=&#34;https://www.theverge.com/24067997/robots-txt-ai-text-file-web-crawlers-spiders&#34;&gt;poor robots.txt&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://gohugo.io/getting-started/configuration/#_404-server-error-page&#34;&gt;404&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;running-the-script&#34;&gt;Running the script&lt;/h2&gt;
&lt;p&gt;I run this script by hand from variables in a .env file, but NOT THE SERVER PASSWORD. If remembering the password every time isn&amp;rsquo;t an option, &lt;a href=&#34;https://www.digitalocean.com/community/tutorials/how-to-copy-files-with-rsync-over-ssh&#34;&gt;use a ssh key&lt;/a&gt;.&lt;/p&gt;
</description>
    </item>
    
    
    
    <item>
      <title>How can I get this SAMD21E18 startup code a little sturdier?</title>
      <link>https://whynotestflight.com/excuses/how-can-i-get-this-samd21e18-startup-code-a-little-sturdier/</link>
      <pubDate>Thu, 11 Apr 2024 00:00:00 +0000</pubDate>
      
      <guid>https://whynotestflight.com/excuses/how-can-i-get-this-samd21e18-startup-code-a-little-sturdier/</guid>
      <description>&lt;p&gt;Related Repo: &lt;a href=&#34;https://github.com/carlynorama/StrippedDownChipRosetta&#34;&gt;https://github.com/carlynorama/StrippedDownChipRosetta&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;At the end of the last post I mentioned that I wasn&amp;rsquo;t going to comment on the code or the linker script, but that I didn&amp;rsquo;t recommend editing them yet. The code from the last post worked because it had workable hooks where they needed to be for what it was trying to do. Many minimal examples work &lt;em&gt;because&lt;/em&gt; they do nothing.  Adding more code in the wrong place can break things with no error messages to help.&lt;/p&gt;
&lt;p&gt;When programming for a machine with an operating system, generally folks can start with the apps entry point, &amp;ldquo;&lt;a href=&#34;https://www.hackingwithswift.com/swift/5.3/atmain&#34;&gt;main&lt;/a&gt;&amp;rdquo;, and go from there. On a microcontroller the software has to be both application and &amp;ldquo;operating system&amp;rdquo;. Thankfully IDEs and frameworks hide a lot of that so folks can get right to work on their idea and only dig deeper if they have a special concern.&lt;/p&gt;
&lt;p&gt;When one does need to go under the hood, the process of setting up a new chip has similarities to learning how to implement a new &lt;a href=&#34;https://docs.swift.org/swift-book/documentation/the-swift-programming-language/protocols/&#34;&gt;Protocol&lt;/a&gt;. There&amp;rsquo;s a contract to deliver on and you have to learn what it is.&lt;/p&gt;
&lt;p&gt;The first step involves providing a start up script that at least:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Defines and places a critical list of function pointers called a &amp;ldquo;vector table&amp;rdquo;. (On Arm® Cortex®-M0+ Processor Core MCU chips the official name of the interrupt handler is the Nested Vectored Interrupt Controller.)&lt;/li&gt;
&lt;li&gt;Initializes two memory areas (.data and .bss)&lt;/li&gt;
&lt;li&gt;Starts the program!&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This post is less tutorial and more record of what I did, what resources I needed and what resources I think others might find helpful to fill in the gaps&lt;/p&gt;
&lt;h2 id=&#34;references&#34;&gt;References&lt;/h2&gt;
&lt;p&gt;Tutorials and repos here. Topic specific links in their sections.&lt;/p&gt;
&lt;h3 id=&#34;official&#34;&gt;Official&lt;/h3&gt;
&lt;p&gt;Writing start up scripts and linker files correctly requires intimate knowledge of the specific microcontroller&amp;rsquo;s physical layout. Smart people focused on concrete goals use manufacture provided versions of these files because the manufacturer in theory knows their chip best (and any &lt;a href=&#34;https://ww1.microchip.com/downloads/en/DeviceDoc/SAM-D21DA1-Family-Silicon-Errata-and-Data-Sheet-Clarification-DS80000760G.pdf&#34;&gt;errata&lt;/a&gt;). To find the all the information needed can take a little digging. These are all the sources I looked at. I will state which one contributed to what as I go.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Most Important Link For Vector Table. Do. Not. Skip.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://developerhelp.microchip.com/xwiki/bin/view/products/mcu-mpu/32bit-mcu/sam/samd21-mcu-overview/samd21-processor-overview/samd21-nvic-overview/&#34;&gt;https://developerhelp.microchip.com/xwiki/bin/view/products/mcu-mpu/32bit-mcu/sam/samd21-mcu-overview/samd21-processor-overview/samd21-nvic-overview/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Product Reference Page&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://www.microchip.com/en-us/product/ATSAMD21E18&#34;&gt;https://www.microchip.com/en-us/product/ATSAMD21E18&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Reachable from here:
&lt;ul&gt;
&lt;li&gt;arm-gcc compiler tools, (come with &lt;a href=&#34;https://www.microchip.com/en-us/tools-resources/develop/microchip-studio&#34;&gt;Atmel Studio&lt;/a&gt; if you have that) &lt;a href=&#34;https://www.microchip.com/en-us/tools-resources/develop/microchip-studio/gcc-compilers&#34;&gt;https://www.microchip.com/en-us/tools-resources/develop/microchip-studio/gcc-compilers&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;http://packs.download.atmel.com/&#34;&gt;http://packs.download.atmel.com/&lt;/a&gt; (rename .atpack files to .zip) (&lt;a href=&#34;https://github.com/Microchip-MPLAB-Harmony/dev_packs/tree/master/Microchip&#34;&gt;packs on github&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://www.keil.arm.com/devices/&#34;&gt;https://www.keil.arm.com/devices/&lt;/a&gt; for CMSIS? Link provided by Microchip. hunh.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Full Family Data Sheet&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://ww1.microchip.com/downloads/aemDocuments/documents/MCU32/ProductDocuments/DataSheets/SAM-D21-DA1-Family-Data-Sheet-DS40001882H.pdf&#34;&gt;https://ww1.microchip.com/downloads/aemDocuments/documents/MCU32/ProductDocuments/DataSheets/SAM-D21-DA1-Family-Data-Sheet-DS40001882H.pdf&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Cortex-M0+ Technical Reference Manual (Revision: r0p1)&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://developer.arm.com/documentation/ddi0484/c/?lang=en&#34;&gt;https://developer.arm.com/documentation/ddi0484/c/?lang=en&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;ARMv6-M Architecture Reference Manual&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;PDF &lt;a href=&#34;https://documentation-service.arm.com/static/5f8ff05ef86e16515cdbf826&#34;&gt;https://documentation-service.arm.com/static/5f8ff05ef86e16515cdbf826&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Online Viewer &lt;a href=&#34;https://developer.arm.com/documentation/ddi0419/latest/&#34;&gt;https://developer.arm.com/documentation/ddi0419/latest/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Demo project repo, &lt;a href=&#34;https://github.com/Microchip-MPLAB-Harmony/reference_apps/blob/143e5438a43c50660b893980bcb41b930dcf9821/apps/sam_d21_cnano/samd21n_getting_started/&#34;&gt;SAMD21N Getting Started&lt;/a&gt;. Needs MPLAB software to run, uses C, but I wanted to look at the list of &lt;a href=&#34;https://github.com/Microchip-MPLAB-Harmony/reference_apps/tree/143e5438a43c50660b893980bcb41b930dcf9821/apps/sam_d21_cnano/samd21n_getting_started/firmware/src/config/sam_d21_cnano&#34;&gt;hardware defs&lt;/a&gt; and &lt;a href=&#34;https://github.com/Microchip-MPLAB-Harmony/reference_apps/blob/143e5438a43c50660b893980bcb41b930dcf9821/apps/sam_d21_cnano/samd21n_getting_started/firmware/src/config/sam_d21_cnano/ATSAMD21G17D.ld&#34;&gt;linker scripts&lt;/a&gt; to double check my work.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/Microchip-MPLAB-Harmony/reference_apps/tree/143e5438a43c50660b893980bcb41b930dcf9821/apps/sam_d21_cnano/samd21n_getting_started/firmware/src/packs&#34;&gt;https://github.com/Microchip-MPLAB-Harmony/reference_apps/tree/143e5438a43c50660b893980bcb41b930dcf9821/apps/sam_d21_cnano/samd21n_getting_started/firmware/src/packs&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&#34;https://github.com/Microchip-MPLAB-Harmony/dev_packs/tree/345dc12d42a4fdec72117b64a8c3527023bdeca9/Microchip/SAMD21_DFP/3.6.144/samd21a/armcc/armcc&#34;&gt;https://github.com/Microchip-MPLAB-Harmony/dev_packs/tree/345dc12d42a4fdec72117b64a8c3527023bdeca9/Microchip/SAMD21_DFP/3.6.144/samd21a/armcc/armcc&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;more-instructional&#34;&gt;More Instructional&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Carry Over: STM32 Based Fastbit Embedded Brain Academy&lt;a href=&#34;https://www.youtube.com/watch?v=qWqlkCLmZoE&amp;amp;list=PLERTijJOmYrDiiWd10iRHY0VRHdJwUH4g&#34;&gt;“Bare metal embedded” playlist.&lt;/a&gt; Especially videos 2 &amp;amp; 3&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Continuation: “Bare Metal” STM32 Programming (Part 2)&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://vivonomicon.com/2018/04/20/bare-metal-stm32-programming-part-2-making-it-to-main/&#34;&gt;https://vivonomicon.com/2018/04/20/bare-metal-stm32-programming-part-2-making-it-to-main/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;If you&amp;rsquo;re using a Pico (RP2040), stop reading this and go&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;read &lt;a href=&#34;https://blog.smittytone.net/2022/06/19/get-started-with-arm-assembly-on-the-pi-pico/&#34;&gt;https://blog.smittytone.net/2022/06/19/get-started-with-arm-assembly-on-the-pi-pico/&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/smittytone/pico-asm/blob/main/source/asm_led_sdk/main.S&#34;&gt;https://github.com/smittytone/pico-asm/blob/main/source/asm_led_sdk/main.S&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;watch (Life With David) &lt;a href=&#34;https://www.youtube.com/playlist?list=PLiRALtgGsxmYTF6ZqDSg4DRWDLGVer-Kb&#34;&gt;https://www.youtube.com/playlist?list=PLiRALtgGsxmYTF6ZqDSg4DRWDLGVer-Kb&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/LifeWithDavid/RaspberryPiPico-BareMetalAdventures/tree/main&#34;&gt;https://github.com/LifeWithDavid/RaspberryPiPico-BareMetalAdventures/tree/main&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&#34;https://forum.digikey.com/t/getting-started-with-the-sam-d21-xplained-pro-without-asf/13176&#34;&gt;https://forum.digikey.com/t/getting-started-with-the-sam-d21-xplained-pro-without-asf/13176&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&#34;https://jacobmossberg.se/posts/2017/01/10/minimalistic-assembler-program-on-stm32-h103.html&#34;&gt;https://jacobmossberg.se/posts/2017/01/10/minimalistic-assembler-program-on-stm32-h103.html&lt;/a&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;armasm source: &lt;a href=&#34;https://pygmy.utoh.org/riscy/cortex/led-stm32.html&#34;&gt;https://pygmy.utoh.org/riscy/cortex/led-stm32.html&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;how-to-search-github&#34;&gt;How to search github&lt;/h3&gt;
&lt;p&gt;When looking for start up scripts to verify my work wasn&amp;rsquo;t totally off base, github searches of:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;SAMD21E18 path:*.s&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;path:*SAMD21* path:*.s&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;path:*SAMD21* path:*.s path:*startup*&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;#ifndef _SAMD21E18A_&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Turned up some of the most useful results.&lt;/p&gt;
&lt;p&gt;To go a little more scatter shot, the following phrases (plus your Microchip part number) are an indicator that file started from the official source. I&amp;rsquo;m sure you can come up with more &amp;ldquo;Statistically Improbable Phrases&amp;rdquo; from the demo projects, etc above.
- &amp;ldquo;\brief Header file for&amp;rdquo;
- &amp;ldquo;Microchip Technology Inc. and its subsidiaries&amp;rdquo;
- &amp;ldquo;Copyright (wild card) Atmel Corporation&amp;rdquo;
- &amp;ldquo;\brief This module contains&amp;rdquo;&lt;/p&gt;
&lt;h3 id=&#34;how-to-compare-assembly-start-up-files&#34;&gt;How To Compare Assembly Start Up Files&lt;/h3&gt;
&lt;p&gt;This will not be a course in assembly, although I&amp;rsquo;ve tried to provide alternate examples and some explanations.&lt;/p&gt;
&lt;p&gt;I mentioned searching github, but assembly start up scripts can look wildly different even for the same chip:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;for tool chain reasons&lt;/li&gt;
&lt;li&gt;for syntax preference reasons&lt;/li&gt;
&lt;li&gt;for what parts of the chip&amp;rsquo;s functionality is actually needed reasons&lt;/li&gt;
&lt;li&gt;for compatibility with other code reasons (will there be C?, is this just for one project or the basis of a library?)&lt;/li&gt;
&lt;li&gt;for stylistic decisions about how to ensure code blocks end up where they&amp;rsquo;re supposed to be reasons (physical placement, naming conventions, manually setting the counter value)&lt;/li&gt;
&lt;li&gt;for stylistic decisions about how much gets handled in the code files vs the linker file reasons (where do you see &amp;ldquo;align&amp;rdquo;)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;It can be reaaaaly hard to tell what&amp;rsquo;s a meaningful difference between two files and what is not. Hopefully the links below will help when my comments aren&amp;rsquo;t good enough.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&#34;https://en.wikipedia.org/wiki/X86_assembly_language#Syntax&#34;&gt;https://en.wikipedia.org/wiki/X86_assembly_language#Syntax&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Nice syntax explanation in a relevant example of a start up (Not M0 though)&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://community.arm.com/arm-community-blogs/b/architectures-and-processors-blog/posts/writing-your-own-startup-code-for-cortex-m&#34;&gt;https://community.arm.com/arm-community-blogs/b/architectures-and-processors-blog/posts/writing-your-own-startup-code-for-cortex-m&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;same code? &lt;a href=&#34;https://github.com/koson/blinky/blob/6029c2ca627b582f7f7b17fc89c888f67f15f7b4/startup/startup_LPC1768.S&#34;&gt;https://github.com/koson/blinky/blob/6029c2ca627b582f7f7b17fc89c888f67f15f7b4/startup/startup_LPC1768.S&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&#34;https://www.chibialiens.com/arm/thumb.php&#34;&gt;https://www.chibialiens.com/arm/thumb.php&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&#34;http://www.coranac.com/tonc/text/asm.htm#sec-thumb&#34;&gt;http://www.coranac.com/tonc/text/asm.htm#sec-thumb&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Intro to Assembly for Arm programming for playlist from last post.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://www.youtube.com/watch?v=in-UY_EyI14&amp;amp;list=PL2EF13wm-hWAlQe87UB2HV0SVhBXFpXbn&#34;&gt;https://www.youtube.com/watch?v=in-UY_EyI14&amp;amp;list=PL2EF13wm-hWAlQe87UB2HV0SVhBXFpXbn&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://cpulator.01xz.net&#34;&gt;https://cpulator.01xz.net&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;MIT Open Courseware &lt;a href=&#34;https://www.youtube.com/watch?v=L1ung0wil9Y&#34;&gt;4. Assembly Language &amp;amp; Computer Architecture&lt;/a&gt; from
MIT 6.172 Performance Engineering of Software Systems, Fall 2018&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;a---a-mildly-better-version&#34;&gt;A - A mildly better version&lt;/h2&gt;
&lt;h3 id=&#34;finding-what-i-needed-to-make-a-vector-table&#34;&gt;Finding what I needed to make a vector table&lt;/h3&gt;
&lt;p&gt;The &amp;ldquo;vector table&amp;rdquo; lists all the addresses of the critical low level functions the chip will need to know what to do when &amp;ldquo;something happens&amp;rdquo;. They must live at exactly the location defined by the architecture and the manufacturer. They are incredibly device dependent, although the nice thing about Arm chips is that they share some values across cores and architectures.&lt;/p&gt;
&lt;p&gt;Some of the types of things that get answered by the vector table are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;what&amp;rsquo;s the first thing I should do?&lt;/li&gt;
&lt;li&gt;what do I do when I fail?&lt;/li&gt;
&lt;li&gt;what do I do with this messages?&lt;/li&gt;
&lt;li&gt;its been 27 ticks - I check where after 27 ticks?&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&#34;misc-overviews&#34;&gt;Misc Overviews&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;Program, Interrupted - Computerphile &lt;a href=&#34;https://www.youtube.com/watch?v=54BrU82ANww&#34;&gt;https://www.youtube.com/watch?v=54BrU82ANww&lt;/a&gt; (6:40)&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://en.wikipedia.org/wiki/Vectored_interrupt&#34;&gt;https://en.wikipedia.org/wiki/Vectored_interrupt&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;18.2.6 Strong Priority Systems &lt;a href=&#34;https://www.youtube.com/watch?v=PmOq8G_hs4o&#34;&gt;https://www.youtube.com/watch?v=PmOq8G_hs4o&lt;/a&gt; from &lt;a href=&#34;https://ocw.mit.edu/courses/6-004-computation-structures-spring-2017/&#34;&gt;Computation Structures&lt;/a&gt; Uses keyboards and printers, but micros have other &amp;ldquo;&lt;a href=&#34;https://embedded.fm/blog/2016/5/16/ese101-peripherals-part-1&#34;&gt;peripherals&lt;/a&gt;&amp;rdquo;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;how-does-that-all-work-on-the-samd21-specifically&#34;&gt;How does that all work on the SAMD21 specifically&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;READ THIS!!!!! &amp;mdash;-&amp;gt; &lt;a href=&#34;https://developerhelp.microchip.com/xwiki/bin/view/products/mcu-mpu/32bit-mcu/sam/samd21-mcu-overview/samd21-processor-overview/samd21-nvic-overview/&#34;&gt;https://developerhelp.microchip.com/xwiki/bin/view/products/mcu-mpu/32bit-mcu/sam/samd21-mcu-overview/samd21-processor-overview/samd21-nvic-overview/&lt;/a&gt; &amp;lt;&amp;mdash;&amp;mdash;&amp;mdash;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;A vector table for a SAMD21 has to deliver on the Arm® Cortex®-M0+ Processor Core MCU requirements as well as support its own peripherals.  The above link is by far the best information I found for this chip.&lt;/p&gt;
&lt;p&gt;Images below from that page:&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;cm0plus-nvic-exception-table.png&#34; alt=&#34;Table from above page&#34;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;samd21-nvic-vector-table-detail_wbkg.png&#34; alt=&#34;picture from that page&#34;&gt;&lt;/p&gt;
&lt;p&gt;But this just tells you about the Cortex-M0+ values. The chip specific information can be tracked down in the Datasheet. Unfortunately I couldn&amp;rsquo;t the find a comprehensive list in one easy place like for the Atmega328 (not Arm, different beast, &lt;a href=&#34;https://ww1.microchip.com/downloads/en/DeviceDoc/Atmel-7810-Automotive-Microcontrollers-ATmega328P_Datasheet.pdf&#34;&gt;table 11-1 in 328 datasheet&lt;/a&gt;) or the STM32F0 (Arm Coretex-M0 (&lt;a href=&#34;https://www.st.com/content/st_com/en/arm-32-bit-microcontrollers/arm-cortex-m0-plus.html&#34;&gt;not M0p&lt;/a&gt;)  &lt;a href=&#34;https://www.st.com/resource/en/reference_manual/rm0091-stm32f0x1stm32f0x2stm32f0x8-advanced-armbased-32bit-mcus-stmicroelectronics.pdf&#34;&gt;Section 11, Table 36 in the reference manual&lt;/a&gt;).  If it wasn&amp;rsquo;t for this one page I&amp;rsquo;m not sure how one would have pulled together the full list except by using sample code.&lt;/p&gt;
&lt;h4 id=&#34;product-mapping&#34;&gt;Product Mapping&lt;/h4&gt;
&lt;p&gt;Datasheet
9 Product Mapping
Figure 9-1. SAM D21 Product Mapping
&lt;img src=&#34;9_f9_1_product_map.png&#34; alt=&#34;product map&#34;&gt;&lt;/p&gt;
&lt;h4 id=&#34;chip-specific-hardware-list&#34;&gt;Chip Specific Hardware List&lt;/h4&gt;
&lt;p&gt;The 0 next to PM - Power Manager lines up with the the &lt;code&gt;16 IRQ 0&lt;/code&gt; in the very first image, and the &lt;code&gt;0 PM_Manager&lt;/code&gt; (addresses 0x00000040)&lt;/p&gt;
&lt;p&gt;Datasheet
11.2 Nested Vector Interrupt Controller
11.2.2 Interrupt Line Mapping&lt;/p&gt;
&lt;p&gt;!!!WARNING!!! &lt;strong&gt;FAMILY&lt;/strong&gt; Datasheet. Cross reference the below with section 2 Configuration Summary (not shown) for which ones your chip specifically implements.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;11_2_t11_3_interupt_line_mapping.png&#34; alt=&#34;table - TODO Switch to HTML table&#34;&gt;&lt;/p&gt;
&lt;h3 id=&#34;updating-hello-code-with-minimal-vector-table--handlers&#34;&gt;Updating Hello Code With Minimal Vector Table &amp;amp; Handlers&lt;/h3&gt;
&lt;p&gt;Between your start up function and the linker file the idea is to defend the expected amount of space at the expected location and fill it with either useful or guaranteed harmless information.&lt;/p&gt;
&lt;p&gt;My first example will only specify Cortex-M0+ needed values. Since embedded chips are small it&amp;rsquo;s not uncommon to not leave space for the features of the chip you know your code (AND CIRCUIT!) won&amp;rsquo;t use.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-asm&#34; data-lang=&#34;asm&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;.syntax&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;unified&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;.cpu&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;cortex-m0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;.fpu&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;softvfp&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;.thumb&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;@&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;vector_table&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;will&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;be&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;at&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;the&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;top&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;of&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;text&lt;/span&gt;, &lt;span style=&#34;color:#eed49f&#34;&gt;because&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;it&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;is&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;at&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;the&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;top&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;of&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;text&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;@&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;and&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;we&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;have&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;no&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;other&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;files.&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#eed49f&#34;&gt;.text&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#91d7e3&#34;&gt;vector_table:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#8aadf4&#34;&gt;.word&lt;/span&gt;   &lt;span style=&#34;color:#eed49f&#34;&gt;sp_initial_value&lt;/span&gt; &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//edge of stack, set in linker
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#8aadf4&#34;&gt;.word&lt;/span&gt;   &lt;span style=&#34;color:#eed49f&#34;&gt;reset_handler&lt;/span&gt;   &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//reset handler
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#8aadf4&#34;&gt;.word&lt;/span&gt;   &lt;span style=&#34;color:#eed49f&#34;&gt;nmi_handler&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#8aadf4&#34;&gt;.word&lt;/span&gt;   &lt;span style=&#34;color:#eed49f&#34;&gt;hard_fault_handler&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#8aadf4&#34;&gt;.word&lt;/span&gt;   &lt;span style=&#34;color:#f5a97f&#34;&gt;0&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//not in M0+
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#8aadf4&#34;&gt;.word&lt;/span&gt;   &lt;span style=&#34;color:#f5a97f&#34;&gt;0&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//not in M0+
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#8aadf4&#34;&gt;.word&lt;/span&gt;   &lt;span style=&#34;color:#f5a97f&#34;&gt;0&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//not in M0+
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#8aadf4&#34;&gt;.word&lt;/span&gt;   &lt;span style=&#34;color:#f5a97f&#34;&gt;0&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//not in M0+
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#8aadf4&#34;&gt;.word&lt;/span&gt;   &lt;span style=&#34;color:#f5a97f&#34;&gt;0&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//not in M0+
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#8aadf4&#34;&gt;.word&lt;/span&gt;   &lt;span style=&#34;color:#f5a97f&#34;&gt;0&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//not in M0+
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#8aadf4&#34;&gt;.word&lt;/span&gt;   &lt;span style=&#34;color:#f5a97f&#34;&gt;0&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//not in M0+
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#8aadf4&#34;&gt;.word&lt;/span&gt;   &lt;span style=&#34;color:#eed49f&#34;&gt;svc_handler&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#8aadf4&#34;&gt;.word&lt;/span&gt;   &lt;span style=&#34;color:#f5a97f&#34;&gt;0&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//not in M0+
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#8aadf4&#34;&gt;.word&lt;/span&gt;   &lt;span style=&#34;color:#f5a97f&#34;&gt;0&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//not in M0+
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#8aadf4&#34;&gt;.word&lt;/span&gt;   &lt;span style=&#34;color:#eed49f&#34;&gt;pendsv_handler&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#8aadf4&#34;&gt;.word&lt;/span&gt;   &lt;span style=&#34;color:#eed49f&#34;&gt;systick_handler&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#8aadf4&#34;&gt;.weakref&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;nmi_handler&lt;/span&gt;, &lt;span style=&#34;color:#eed49f&#34;&gt;default_handler&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#8aadf4&#34;&gt;.weakref&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;hard_fault_handler&lt;/span&gt;, &lt;span style=&#34;color:#eed49f&#34;&gt;default_handler&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#8aadf4&#34;&gt;.weakref&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;svc_handler&lt;/span&gt;, &lt;span style=&#34;color:#eed49f&#34;&gt;default_handler&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#8aadf4&#34;&gt;.weakref&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;pendsv_handler&lt;/span&gt;, &lt;span style=&#34;color:#eed49f&#34;&gt;default_handler&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#8aadf4&#34;&gt;.weakref&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;systick_handler&lt;/span&gt;, &lt;span style=&#34;color:#eed49f&#34;&gt;default_handler&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;.word&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;default_handler&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;.thumb_func&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#91d7e3&#34;&gt;default_handler:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   &lt;span style=&#34;color:#8aadf4&#34;&gt;ldr&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;r3&lt;/span&gt;, &lt;span style=&#34;color:#ed8796&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#0x8BADF00D
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;   &lt;span style=&#34;color:#ed8796&#34;&gt;@&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;hangs&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;the&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;program.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   &lt;span style=&#34;color:#8aadf4&#34;&gt;b&lt;/span&gt; .
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;.global&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;reset_handler&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;.thumb_func&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#91d7e3&#34;&gt;reset_handler:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#8aadf4&#34;&gt;LDR&lt;/span&gt;  &lt;span style=&#34;color:#eed49f&#34;&gt;r0&lt;/span&gt;, &lt;span style=&#34;color:#ed8796&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#eed49f&#34;&gt;sp_initial_value&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#8aadf4&#34;&gt;MOV&lt;/span&gt;  &lt;span style=&#34;color:#eed49f&#34;&gt;sp&lt;/span&gt;, &lt;span style=&#34;color:#eed49f&#34;&gt;r0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#8aadf4&#34;&gt;LDR&lt;/span&gt;  &lt;span style=&#34;color:#eed49f&#34;&gt;r7&lt;/span&gt;, &lt;span style=&#34;color:#ed8796&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#f5a97f&#34;&gt;0xF0CACC1A&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#8aadf4&#34;&gt;MOVS&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;r0&lt;/span&gt;, &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#0
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;  &lt;span style=&#34;color:#91d7e3&#34;&gt;main_loop:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;@&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;Add&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;1&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;to&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;register&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#eed49f&#34;&gt;r0&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;&amp;#39;&lt;/span&gt;.
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#8aadf4&#34;&gt;ADDS&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;r0&lt;/span&gt;, &lt;span style=&#34;color:#eed49f&#34;&gt;r0&lt;/span&gt;, &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#1
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;@&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;Loop&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;back.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#8aadf4&#34;&gt;B&lt;/span&gt;    &lt;span style=&#34;color:#eed49f&#34;&gt;main_loop&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;I&amp;rsquo;m using a different syntax than the &lt;a href=&#34;https://vivonomicon.com/2018/04/20/bare-metal-stm32-programming-part-2-making-it-to-main/&#34;&gt;the vivonomicon version&lt;/a&gt;. This version of the code WILL NOT WORK for non-thumb mode arm processors. I&amp;rsquo;ll revert to that more core flexible syntax, using the gcc assembler directive &lt;a href=&#34;https://sourceware.org/binutils/docs/as/Type.html#Type&#34;&gt;.type&lt;/a&gt;, in code where I care about portability.&lt;/p&gt;
&lt;p&gt;Each interrupt gets a &lt;code&gt;weakref&lt;/code&gt; (search on &lt;a href=&#34;https://gcc.gnu.org/onlinedocs/gcc-10.2.0/gcc/Common-Function-Attributes.html&#34;&gt;this gnu docs page&lt;/a&gt;) to a default handler function. This lets a future user of this code override their values in another file. I could have just put &lt;code&gt;default_handler&lt;/code&gt; everywhere I put a unique function name in the vector table. You might see this weak ref creation in other files as:&lt;/p&gt;
&lt;p&gt;A &lt;a href=&#34;https://github.com/search?q=+.weak+++++++SysTick_Handler+++++.thumb_set++SysTick_Handler%2C+Default_Handler&amp;amp;type=code&#34;&gt;two step process&lt;/a&gt;&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-asm&#34; data-lang=&#34;asm&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#8aadf4&#34;&gt;.weak&lt;/span&gt;       &lt;span style=&#34;color:#eed49f&#34;&gt;SysTick_Handler&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#8aadf4&#34;&gt;.thumb_set&lt;/span&gt;  &lt;span style=&#34;color:#eed49f&#34;&gt;SysTick_Handler&lt;/span&gt;, &lt;span style=&#34;color:#eed49f&#34;&gt;Default_Handler&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;A different flavor of assembly (armasm, not the now recommended by Arm gccasm) in some of the &lt;a href=&#34;https://github.com/Microchip-MPLAB-Harmony/dev_packs/tree/345dc12d42a4fdec72117b64a8c3527023bdeca9/Microchip/SAMD21_DFP/3.6.144/samd21a/armcc/armcc&#34;&gt;official docs&lt;/a&gt;&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-asm&#34; data-lang=&#34;asm&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;SysTick_Handler&lt;/span&gt;           &lt;span style=&#34;color:#eed49f&#34;&gt;PROC&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                          &lt;span style=&#34;color:#8aadf4&#34;&gt;EXPORT&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;SysTick_Handler&lt;/span&gt;           [&lt;span style=&#34;color:#eed49f&#34;&gt;WEAK&lt;/span&gt;] 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                          &lt;span style=&#34;color:#eed49f&#34;&gt;B&lt;/span&gt;       .
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                          &lt;span style=&#34;color:#8aadf4&#34;&gt;ENDP&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Handled by a macro as suggested in &lt;a href=&#34;https://github.com/search?q=.macro+IRQ+handler+++++.weak++%5Chandler+++++.set+++%5Chandler%2C+Default_Handler+.endm+path%3Aarm&amp;amp;type=code&#34;&gt;Arm provided code&lt;/a&gt; (set vs thumb_set depending on the instruction set)&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-asm&#34; data-lang=&#34;asm&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;.macro&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;IRQ&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;handler&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#8aadf4&#34;&gt;.weak&lt;/span&gt;  &lt;span style=&#34;color:#ed8796&#34;&gt;\&lt;/span&gt;&lt;span style=&#34;color:#eed49f&#34;&gt;handler&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#8aadf4&#34;&gt;.set&lt;/span&gt;   &lt;span style=&#34;color:#ed8796&#34;&gt;\&lt;/span&gt;&lt;span style=&#34;color:#eed49f&#34;&gt;handler&lt;/span&gt;, &lt;span style=&#34;color:#eed49f&#34;&gt;Default_Handler&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;.endm&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;IRQ&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;SysTick_Handler&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Or even good old&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-C&#34; data-lang=&#34;C&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;void&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;SysTick_Handler&lt;/span&gt;(&lt;span style=&#34;color:#ed8796&#34;&gt;void&lt;/span&gt;) &lt;span style=&#34;color:#8aadf4&#34;&gt;__attribute__&lt;/span&gt; ((weak, &lt;span style=&#34;color:#8aadf4&#34;&gt;alias&lt;/span&gt; (&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Default_Handler&amp;#34;&lt;/span&gt;)));
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;These all serve the same purpose.&lt;/p&gt;
&lt;p&gt;Another thing you might see in thumb mode vector tables is &lt;code&gt;+ 1&lt;/code&gt; to the function address or some &lt;code&gt;.align N&lt;/code&gt; where N is odd before a function declaration later in the code or something somewhere that shifts the handler addresses so the least significant bit of the address will be 1. I put some links in the assembly link section above and yesterday that cover how the assembler can tell if it should be using 16 or 32 bit instructions by the lsb.  It comes up a lot.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://stackoverflow.com/questions/27118795/cortex-m0-linker-script-and-startup-code/27128307#27128307&#34;&gt;https://stackoverflow.com/questions/27118795/cortex-m0-linker-script-and-startup-code/27128307#27128307&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://stackoverflow.com/questions/77060865/thumb-func-directive-is-not-accounted-for&#34;&gt;https://stackoverflow.com/questions/77060865/thumb-func-directive-is-not-accounted-for&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://stackoverflow.com/questions/4423211/when-are-gas-elf-the-directives-type-thumb-size-and-section-needed&#34;&gt;https://stackoverflow.com/questions/4423211/when-are-gas-elf-the-directives-type-thumb-size-and-section-needed&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://wiki.segger.com/Correct_typing_of_Thumb_functions&#34;&gt;https://wiki.segger.com/Correct_typing_of_Thumb_functions&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://community.arm.com/support-forums/f/architectures-and-processors-forum/4167/difference-between-thumb-machine-directives&#34;&gt;https://community.arm.com/support-forums/f/architectures-and-processors-forum/4167/difference-between-thumb-machine-directives&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Thankfully &lt;code&gt;.thumb_func&lt;/code&gt; should be taking care of that for me. The &lt;code&gt;=mthumb&lt;/code&gt; in the gcc calls should do that too when using the .type directive. (&lt;code&gt;.type name, %function&lt;/code&gt;), but I haven&amp;rsquo;t confirmed that yet.&lt;/p&gt;
&lt;h3 id=&#34;mildly-improving-the-linker&#34;&gt;Mildly Improving the Linker&lt;/h3&gt;
&lt;p&gt;This program relies on the vector table being defined in  &lt;em&gt;the one&lt;/em&gt; source file immediately after the &lt;a href=&#34;https://armasm.com/docs/getting-to-hello-world/basics/#file-format&#34;&gt;&lt;code&gt;.text&lt;/code&gt;&lt;/a&gt;&lt;a href=&#34;https://downloads.ti.com/docs/esd/SLAU131K/Content/SLAU131K_HTML/assembler_directives.html&#34;&gt;compiler&lt;/a&gt; &lt;a href=&#34;https://community.arm.com/arm-community-blogs/b/architectures-and-processors-blog/posts/useful-assembler-directives-and-macros-for-the-gnu-assembler&#34;&gt;directive&lt;/a&gt; is invoked.  I&amp;rsquo;ll make a more resilient set up next. The compiler already has opinions about what to do with .text, so you &lt;a href=&#34;https://stackoverflow.com/questions/16283769/are-text-and-data-required-in-arm-assembly&#34;&gt;could leave it out in other circumstances&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;How does this differ from the &lt;a href=&#34;https://github.com/carlynorama/StrippedDownChipRosetta/blob/main/ARM/SAMD21E18/01_AssemblyHello/hello.ld&#34;&gt;previous file&lt;/a&gt;?&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;changes the entry point officially &lt;a href=&#34;https://ftp.gnu.org/old-gnu/Manuals/ld-2.9.1/html_node/ld_24.html&#34;&gt;ENTRY&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;uses the &lt;a href=&#34;https://ftp.gnu.org/old-gnu/Manuals/ld-2.9.1/html_node/ld_17.html#SEC17&#34;&gt;SECTIONS&lt;/a&gt; command with some of the linker software special-treatment section names (text, data, bss) [todo links]&lt;/li&gt;
&lt;li&gt;sweeps in those sections from &lt;em&gt;ALL&lt;/em&gt; files.&lt;/li&gt;
&lt;li&gt;places those sections with &lt;a href=&#34;https://ftp.gnu.org/old-gnu/Manuals/ld-2.9.1/html_node/ld_21.html&#34;&gt;&amp;gt; AT&lt;/a&gt; based on the defined memory locations&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-C&#34; data-lang=&#34;C&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;ENTRY&lt;/span&gt;(reset_handler);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;MEMORY {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#8aadf4&#34;&gt;flash&lt;/span&gt;(rx)&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;:&lt;/span&gt; ORIGIN &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;0x00000000&lt;/span&gt;, LENGTH &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;0x00040000&lt;/span&gt; &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;/*256K*/&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#8aadf4&#34;&gt;sram&lt;/span&gt;(rwx)&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;:&lt;/span&gt; ORIGIN &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;0x20000000&lt;/span&gt;, LENGTH &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;0x00008000&lt;/span&gt; &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;/*32K*/&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;sp_initial_value &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;ORIGIN&lt;/span&gt;(sram) &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;+&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;LENGTH&lt;/span&gt;(sram);  &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;/* 0x20008000 */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;SECTIONS {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    .&lt;span style=&#34;color:#91d7e3&#34;&gt;text&lt;/span&gt;   : { &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;*&lt;/span&gt;(.text)  } &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;gt;&lt;/span&gt; flash
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    .&lt;span style=&#34;color:#91d7e3&#34;&gt;data&lt;/span&gt; : { &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;*&lt;/span&gt;(.data) } &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;gt;&lt;/span&gt; sram AT&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;gt;&lt;/span&gt; flash
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    .&lt;span style=&#34;color:#91d7e3&#34;&gt;bss&lt;/span&gt;    : { &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;*&lt;/span&gt;(.bss)    } &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;gt;&lt;/span&gt; sram
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;More links on linker files later.&lt;/p&gt;
&lt;h2 id=&#34;b---separating-the-startup-from-the-program-code&#34;&gt;B - Separating the Startup from The Program Code&lt;/h2&gt;
&lt;p&gt;This code works (use the makefile), but it&amp;rsquo;s still fragile.  What the chip needs and our wants are all mushed together and everything relies on putting things in the right place in the file. And we haven&amp;rsquo;t even done some of the important startup basics.&lt;/p&gt;
&lt;h3 id=&#34;1---pull-out-the-main-loop-still-one-file&#34;&gt;1 - Pull out the Main Loop, Still one File&lt;/h3&gt;
&lt;p&gt;First I changed hello_improved to hello_main, pulling out the loop in the same file &lt;a href=&#34;https://community.arm.com/arm-community-blogs/b/architectures-and-processors-blog/posts/branch-and-call-sequences-explained&#34;&gt;via branching&lt;/a&gt;. I did not following all the proper &lt;a href=&#34;https://en.wikipedia.org/wiki/Calling_convention&#34;&gt;calling conventions&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;hello_main also has new section markers, which were tested by adding them in the linker an running the shiny new disassemble command in the makefile.&lt;/p&gt;
&lt;p&gt;This is all in &lt;a href=&#34;https://github.com/carlynorama/StrippedDownChipRosetta/tree/main/ARM/SAMD21E18/02_AssemblyStartUp/b_hello_with_main_thumb/1_single_file_sections&#34;&gt;the repo here&lt;/a&gt;&lt;/p&gt;
&lt;h3 id=&#34;2--doing-more-for-the-start-up&#34;&gt;2- Doing more for the start up&lt;/h3&gt;
&lt;p&gt;&lt;a href=&#34;https://github.com/carlynorama/StrippedDownChipRosetta/tree/main/ARM/SAMD21E18/02_AssemblyStartUp/b_hello_with_main_thumb/2_single_file_startup&#34;&gt;repo folder&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;When looking for the right assembly syntax for the reset handler I was influenced by the following scripts:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://vivonomicon.com/2018/04/20/bare-metal-stm32-programming-part-2-making-it-to-main/&#34;&gt;https://vivonomicon.com/2018/04/20/bare-metal-stm32-programming-part-2-making-it-to-main/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Same with different copyrights? (armasm)
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/microsoft/uf2-samdx1/blob/4c900345561949f1c37a367d72eb8e420b01f72f/lib/samd21/samd21a/armcc/Device/SAMD21/Source/ARM/startup_SAMD21.s&#34;&gt;https://github.com/microsoft/uf2-samdx1/blob/4c900345561949f1c37a367d72eb8e420b01f72f/lib/samd21/samd21a/armcc/Device/SAMD21/Source/ARM/startup_SAMD21.s&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/Microchip-MPLAB-Harmony/dev_packs/blob/345dc12d42a4fdec72117b64a8c3527023bdeca9/Microchip/SAMD21_DFP/3.6.144/samd21a/armcc/armcc/startup_samd21e18a.s&#34;&gt;https://github.com/Microchip-MPLAB-Harmony/dev_packs/blob/345dc12d42a4fdec72117b64a8c3527023bdeca9/Microchip/SAMD21_DFP/3.6.144/samd21a/armcc/armcc/startup_samd21e18a.s&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/apache/mynewt-core/blob/158c30fa78f6a93eb267896380f2a03a93cc1527/hw/bsp/arduino_zero/src/arch/cortex_m0/startup_samd21xx.s&#34;&gt;https://github.com/apache/mynewt-core/blob/158c30fa78f6a93eb267896380f2a03a93cc1527/hw/bsp/arduino_zero/src/arch/cortex_m0/startup_samd21xx.s&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://electronics.stackexchange.com/a/452035&#34;&gt;https://electronics.stackexchange.com/a/452035&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://gist.github.com/ppannuto/672328eb8184abdb9559&#34;&gt;https://gist.github.com/ppannuto/672328eb8184abdb9559&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;TODO: Benchmark them. I&amp;rsquo;m not doing anything fancy enough with this code to really make a difference.&lt;/p&gt;
&lt;p&gt;I haven&amp;rsquo;t commented every line. Some assistance (also last post&amp;rsquo;s links&amp;hellip;):&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://documentation-service.arm.com/static/5ed67dc7ca06a95ce53f9334&#34;&gt;thumb instruction quick reference card&lt;/a&gt; by arm&lt;/li&gt;
&lt;li&gt;Fancier branching:
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://azeria-labs.com/arm-conditional-execution-and-branching-part-6/&#34;&gt;https://azeria-labs.com/arm-conditional-execution-and-branching-part-6/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Multi register handling:
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://developer.arm.com/documentation/dui0170/b/thumb-instruction-reference/thumb-memory-access-instructions/ldmia-and-stmia?lang=en&#34;&gt;https://developer.arm.com/documentation/dui0170/b/thumb-instruction-reference/thumb-memory-access-instructions/ldmia-and-stmia?lang=en&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://azeria-labs.com/load-and-store-multiple-part-5/&#34;&gt;https://azeria-labs.com/load-and-store-multiple-part-5/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;What&amp;rsquo;s the deal with _sidata
&lt;ul&gt;
&lt;li&gt;since data is relocatable (unlike text), we need the &amp;ldquo;real&amp;rdquo; address once available.&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://en.wikipedia.org/wiki/Data_segment&#34;&gt;https://en.wikipedia.org/wiki/Data_segment&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://ftp.gnu.org/old-gnu/Manuals/ld-2.9.1/html_chapter/ld_3.html#SEC14&#34;&gt;LOADADDR&lt;/a&gt; in the docs: &amp;ldquo;Return the absolute load address of the named section. This is normally the same as ADDR, but it may be different if the AT keyword is used in the section definition&amp;rdquo;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://ftp.gnu.org/old-gnu/Manuals/ld-2.9.1/html_chapter/ld_3.html#SEC21&#34;&gt;NOLOAD&lt;/a&gt; starts showing up next to bss in fancier linkers - &lt;a href=&#34;https://stackoverflow.com/questions/57181652/understanding-linker-script-noload-sections-in-embedded-software&#34;&gt;discussion&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;more about linkers:
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://www.lurklurk.org/linkers/linkers.html&#34;&gt;https://www.lurklurk.org/linkers/linkers.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://mcyoung.xyz/2021/06/01/linker-script/&#34;&gt;https://mcyoung.xyz/2021/06/01/linker-script/&lt;/a&gt;  via &lt;a href=&#34;https://forums.swift.org/t/embedded-swift-example-projects-for-arm-and-risc-v-microcontrollers/71066/20&#34;&gt;Swift Forum&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://allthingsembedded.com/post/2020-04-11-mastering-the-gnu-linker-script/&#34;&gt;https://allthingsembedded.com/post/2020-04-11-mastering-the-gnu-linker-script/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;working with variable in gcc assembly (to test this worked)
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://azeria-labs.com/memory-instructions-load-and-store-part-4/&#34;&gt;https://azeria-labs.com/memory-instructions-load-and-store-part-4/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://ftp.gnu.org/old-gnu/Manuals/ld-2.9.1/html_chapter/ld_3.html#SEC14&#34;&gt;ALIGN&lt;/a&gt; (right under LOADADDR) and why &lt;a href=&#34;https://softwareengineering.stackexchange.com/questions/328775/how-important-is-memory-alignment-does-it-still-matter&#34;&gt;memory alignment&lt;/a&gt; is important.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&#34;the-new-reset-handler-code&#34;&gt;The new reset handler code&lt;/h4&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-asm&#34; data-lang=&#34;asm&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;.section&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;.text.reset_handler&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;@&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;The&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;Reset&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;Handler&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#eed49f&#34;&gt;.global&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;reset_handler&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;.thumb_func&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#91d7e3&#34;&gt;reset_handler:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;/* reset handler started */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;/* r7 will hold my notes to self  */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#8aadf4&#34;&gt;ldr&lt;/span&gt;  &lt;span style=&#34;color:#eed49f&#34;&gt;r7&lt;/span&gt;, &lt;span style=&#34;color:#ed8796&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#f5a97f&#34;&gt;0x0000AAAA&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;/* set stack pointer */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#8aadf4&#34;&gt;ldr&lt;/span&gt;  &lt;span style=&#34;color:#eed49f&#34;&gt;r1&lt;/span&gt;, &lt;span style=&#34;color:#ed8796&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#eed49f&#34;&gt;_end_stack&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#8aadf4&#34;&gt;mov&lt;/span&gt;  &lt;span style=&#34;color:#eed49f&#34;&gt;sp&lt;/span&gt;, &lt;span style=&#34;color:#eed49f&#34;&gt;r1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;/* set  .bss section to 0 (SRAM) */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;/* uses the jump to exit style loop */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#91d7e3&#34;&gt;zero_bss:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;/* get 0 handy in two registers */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#8aadf4&#34;&gt;movs&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;r0&lt;/span&gt;, &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#0
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#8aadf4&#34;&gt;movs&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;r1&lt;/span&gt;, &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#0
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;/* get the bounds */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#8aadf4&#34;&gt;ldr&lt;/span&gt;  &lt;span style=&#34;color:#eed49f&#34;&gt;r2&lt;/span&gt;, &lt;span style=&#34;color:#ed8796&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;_start_bss&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#8aadf4&#34;&gt;ldr&lt;/span&gt;  &lt;span style=&#34;color:#eed49f&#34;&gt;r3&lt;/span&gt;, &lt;span style=&#34;color:#ed8796&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;_end_bss&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#91d7e3&#34;&gt;loop_start_bss_zero:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;/* compare, first one is that there is a bss.  */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#8aadf4&#34;&gt;cmp&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;r2&lt;/span&gt;, &lt;span style=&#34;color:#eed49f&#34;&gt;r3&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;/* compare: unsigned higher or same (is end higher than current )  */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#8aadf4&#34;&gt;bhs&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;loop_end_bss_zero&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;/* will load 2 and increase the pointer after */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#ed8796&#34;&gt;@&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;stmia&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;r2&lt;/span&gt;!, &lt;span style=&#34;color:#ed8796&#34;&gt;{&lt;/span&gt;&lt;span style=&#34;color:#eed49f&#34;&gt;r0&lt;/span&gt;,&lt;span style=&#34;color:#eed49f&#34;&gt;r1&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#8aadf4&#34;&gt;stmia&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;r2&lt;/span&gt;!, &lt;span style=&#34;color:#ed8796&#34;&gt;{&lt;/span&gt;&lt;span style=&#34;color:#eed49f&#34;&gt;r0&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;}&lt;/span&gt; &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;/* decided against moving bss to after data in linker  */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#8aadf4&#34;&gt;b&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;loop_start_bss_zero&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#91d7e3&#34;&gt;loop_end_bss_zero:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;/* copy .data section to SRAM */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;/* uses the jump to entry style loop */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#91d7e3&#34;&gt;move_data_to_ram:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;/* get the bounds */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#8aadf4&#34;&gt;ldr&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;r0&lt;/span&gt;, &lt;span style=&#34;color:#ed8796&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;_start_data&lt;/span&gt;   
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#eed49f&#34;&gt;ldr&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;r1&lt;/span&gt;, &lt;span style=&#34;color:#ed8796&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;_end_data&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;/* read head location */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#8aadf4&#34;&gt;ldr&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;r2&lt;/span&gt;, &lt;span style=&#34;color:#ed8796&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;_sidata&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#8aadf4&#34;&gt;b&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;loop_enter_data_copy&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#91d7e3&#34;&gt;loop_action_data_copy:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#8aadf4&#34;&gt;ldmia&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;r2&lt;/span&gt;!, &lt;span style=&#34;color:#ed8796&#34;&gt;{&lt;/span&gt;&lt;span style=&#34;color:#eed49f&#34;&gt;r3&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#8aadf4&#34;&gt;stmia&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;r0&lt;/span&gt;!, &lt;span style=&#34;color:#ed8796&#34;&gt;{&lt;/span&gt;&lt;span style=&#34;color:#eed49f&#34;&gt;r3&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#91d7e3&#34;&gt;loop_enter_data_copy:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#8aadf4&#34;&gt;cmp&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;r0&lt;/span&gt;, &lt;span style=&#34;color:#eed49f&#34;&gt;r1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#8aadf4&#34;&gt;bcc&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;loop_action_data_copy&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;/* call the clock system initialization function.*/&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;/* not done */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;/* call init of libraries (stdlib when loop in C) that need it.*/&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;/* not done */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;/* note to self handler finished */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#8aadf4&#34;&gt;LDR&lt;/span&gt;  &lt;span style=&#34;color:#eed49f&#34;&gt;r7&lt;/span&gt;, &lt;span style=&#34;color:#ed8796&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#f5a97f&#34;&gt;0x0000BBBB&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;/* Call the application&amp;#39;s entry point.*/&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#8aadf4&#34;&gt;bl&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;my_main&lt;/span&gt;             
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And the top of the file with lots of variables to test&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-asm&#34; data-lang=&#34;asm&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;.bss&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;/* note, bss is marked noload in the linker */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;/* no matter how long, shouldn&amp;#39;t effect size of elf */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;/* assembler wont let you store values that aren&amp;#39;t 0 */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#91d7e3&#34;&gt;make:&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;.word&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#91d7e3&#34;&gt;something:&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;.word&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#91d7e3&#34;&gt;be:&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;.word&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#91d7e3&#34;&gt;here:&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;.word&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;.data&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;/* like define, but tricksy. */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;.equ&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;pelargonium&lt;/span&gt;, &lt;span style=&#34;color:#f5a97f&#34;&gt;0x600dCA7&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;.equ&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;rosebud&lt;/span&gt;, &lt;span style=&#34;color:#f5a97f&#34;&gt;0xF0CACC1A&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;/* variables with values */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#91d7e3&#34;&gt;ennie:&lt;/span&gt;  &lt;span style=&#34;color:#8aadf4&#34;&gt;.word&lt;/span&gt;  &lt;span style=&#34;color:#f5a97f&#34;&gt;124&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#91d7e3&#34;&gt;meenie:&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;.word&lt;/span&gt;  &lt;span style=&#34;color:#f5a97f&#34;&gt;125&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#91d7e3&#34;&gt;mineie:&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;.word&lt;/span&gt;  &lt;span style=&#34;color:#f5a97f&#34;&gt;126&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#91d7e3&#34;&gt;moe:&lt;/span&gt;    &lt;span style=&#34;color:#8aadf4&#34;&gt;.word&lt;/span&gt;  &lt;span style=&#34;color:#f5a97f&#34;&gt;127&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;@&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;this&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;is&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;NOT&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;how&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;you&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;create&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;unallocated&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;memory&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;@&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;these&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;all&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;point&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;to&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;the&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;same&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;place&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;in&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;memory.&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#eed49f&#34;&gt;breakfast&lt;/span&gt;:  &lt;span style=&#34;color:#eed49f&#34;&gt;.word&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#91d7e3&#34;&gt;lunch:&lt;/span&gt;      &lt;span style=&#34;color:#8aadf4&#34;&gt;.word&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#91d7e3&#34;&gt;dinner:&lt;/span&gt;     &lt;span style=&#34;color:#8aadf4&#34;&gt;.word&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#91d7e3&#34;&gt;midnight_snack:&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;.word&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;27&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#eed49f&#34;&gt;adr_ennie&lt;/span&gt;: &lt;span style=&#34;color:#eed49f&#34;&gt;.word&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;ennie&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#91d7e3&#34;&gt;adr_meenie:&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;.word&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;meenie&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#91d7e3&#34;&gt;adr_mineie:&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;.word&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;mineie&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#eed49f&#34;&gt;adr_moe&lt;/span&gt;: &lt;span style=&#34;color:#eed49f&#34;&gt;.word&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;moe&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#91d7e3&#34;&gt;adr_breakfast:&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;.word&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;breakfast&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#91d7e3&#34;&gt;adr_lunch:&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;.word&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;lunch&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#91d7e3&#34;&gt;adr_dinner:&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;.word&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;dinner&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#91d7e3&#34;&gt;adr_midnight_snack:&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;.word&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;midnight_snack&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#91d7e3&#34;&gt;adr_make:&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;.word&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;make&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#91d7e3&#34;&gt;increment:&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;.word&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;.section&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;.text.program_code&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;.word&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;my_main&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;.thumb_func&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#91d7e3&#34;&gt;my_main:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;/* note to self main started finished */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#8aadf4&#34;&gt;LDR&lt;/span&gt;  &lt;span style=&#34;color:#eed49f&#34;&gt;r7&lt;/span&gt;, &lt;span style=&#34;color:#ed8796&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#f5a97f&#34;&gt;0x0000CCCC&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#ed8796&#34;&gt;@&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;values&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;of&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;the&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;unallocated&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;should&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;match&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#ed8796&#34;&gt;@&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;ennie-moe&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;after&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;done&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;with&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;this.&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#eed49f&#34;&gt;LDR&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;r0&lt;/span&gt;, &lt;span style=&#34;color:#ed8796&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#eed49f&#34;&gt;ennie&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#8aadf4&#34;&gt;ldmia&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;r0&lt;/span&gt;!, &lt;span style=&#34;color:#ed8796&#34;&gt;{&lt;/span&gt;&lt;span style=&#34;color:#eed49f&#34;&gt;r1-r4&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#8aadf4&#34;&gt;LDR&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;r0&lt;/span&gt;, &lt;span style=&#34;color:#ed8796&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#eed49f&#34;&gt;make&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#8aadf4&#34;&gt;stmia&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;r0&lt;/span&gt;!, &lt;span style=&#34;color:#ed8796&#34;&gt;{&lt;/span&gt;&lt;span style=&#34;color:#eed49f&#34;&gt;r1-r4&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;/* start with 0 */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#8aadf4&#34;&gt;movs&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;r0&lt;/span&gt;, &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#0
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;  &lt;span style=&#34;color:#91d7e3&#34;&gt;loop_start:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// Add 1 to register &amp;#39;r0&amp;#39;.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#8aadf4&#34;&gt;ADDS&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;r0&lt;/span&gt;, &lt;span style=&#34;color:#eed49f&#34;&gt;r0&lt;/span&gt;, &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#1
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;  &lt;span style=&#34;color:#8aadf4&#34;&gt;b&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;loop_start&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;the-matching-linker&#34;&gt;The Matching Linker&lt;/h3&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-C&#34; data-lang=&#34;C&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;ENTRY&lt;/span&gt;(reset_handler);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;MEMORY {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#8aadf4&#34;&gt;flash&lt;/span&gt;(rx)&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;:&lt;/span&gt; ORIGIN &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;0x00000000&lt;/span&gt;, LENGTH &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;0x00040000&lt;/span&gt; &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;/*256K*/&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#8aadf4&#34;&gt;sram&lt;/span&gt;(rwx)&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;:&lt;/span&gt; ORIGIN &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;0x20000000&lt;/span&gt;, LENGTH &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;0x00008000&lt;/span&gt; &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;/*32K*/&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;_end_stack &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;ORIGIN&lt;/span&gt;(sram) &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;+&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;LENGTH&lt;/span&gt;(sram);  &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;/* 0x20008000 */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;SECTIONS {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    .&lt;span style=&#34;color:#91d7e3&#34;&gt;text&lt;/span&gt; : { 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        hello_startup.&lt;span style=&#34;color:#8aadf4&#34;&gt;o&lt;/span&gt;(.vectors)  
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#8aadf4&#34;&gt;KEEP&lt;/span&gt;(&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;*&lt;/span&gt;(.vectors .vectors.&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;*&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;*&lt;/span&gt;(.text.reset_handler)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;*&lt;/span&gt;(.text.default_handler)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;/* the rest of the .text and .text sub sections */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;*&lt;/span&gt;(.text .text.&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;*&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;/* all files read only data and read only data sub sections */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;*&lt;/span&gt;(.rodata, .rodata&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;*&lt;/span&gt;) &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;/* read only data */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;       
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    } &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;gt;&lt;/span&gt; flash &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;/* nothing relocatable */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    . &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;ALIGN&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;4&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    _end_text &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; .; &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;/* store current location counter value in _end_text */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;/* Used by the startup to initialize data with the &amp;#34;originating&amp;#34; address */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;/* not so relevant on the M0+, more significant diff on beefier cores */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    _sidata &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;LOADADDR&lt;/span&gt;(.data);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    .&lt;span style=&#34;color:#91d7e3&#34;&gt;data&lt;/span&gt; : { 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        . &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;ALIGN&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;4&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        _start_data &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; .; &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;/* store current location in _end_data t*/&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;*&lt;/span&gt;(.data) 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        . &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;ALIGN&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;4&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        _end_data &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; .; &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;/* store current location in _end_data t*/&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    } &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;gt;&lt;/span&gt; sram AT&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;gt;&lt;/span&gt; flash
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    .&lt;span style=&#34;color:#8aadf4&#34;&gt;bss&lt;/span&gt;(NOLOAD) &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;:&lt;/span&gt; { 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        . &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;ALIGN&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;4&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        _start_bss &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; .;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;*&lt;/span&gt;(.bss) 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;         &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;*&lt;/span&gt;(COMMON) 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;     } &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;gt;&lt;/span&gt; sram
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;     &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;/* todo, inside or outside */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;     . &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;ALIGN&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;4&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;     _end_bss &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; .;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;c---splitting-the-code-into-separate-files&#34;&gt;C - Splitting The Code Into Separate Files&lt;/h2&gt;
&lt;p&gt;Honestly. It just worked.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;split the files&lt;/li&gt;
&lt;li&gt;change the name of hard include in the linker&lt;/li&gt;
&lt;li&gt;updated the Makefile to pull in two files (vey unpolished. I&amp;rsquo;ll fix it later.)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;a href=&#34;https://github.com/carlynorama/StrippedDownChipRosetta/tree/main/ARM/SAMD21E18/02_AssemblyStartUp/b_hello_with_main_thumb/3_multi_file_thumb&#34;&gt;Direct link&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The really change is finally adding in all the peripherals! (see Table 2-1 (Configuration Summary). Some of those are 0s b/c not on the E version of the chip)&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-asm&#34; data-lang=&#34;asm&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;.section&lt;/span&gt;  &lt;span style=&#34;color:#eed49f&#34;&gt;.vectors&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;.global&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;vector_table&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#91d7e3&#34;&gt;vector_table:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//-------------- arm core list
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#8aadf4&#34;&gt;.word&lt;/span&gt;   &lt;span style=&#34;color:#eed49f&#34;&gt;_end_stack&lt;/span&gt; &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//edge of stack, set in linker
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#8aadf4&#34;&gt;.word&lt;/span&gt;   &lt;span style=&#34;color:#eed49f&#34;&gt;reset_handler&lt;/span&gt; &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//reset handler
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#8aadf4&#34;&gt;.word&lt;/span&gt;   &lt;span style=&#34;color:#eed49f&#34;&gt;nmi_handler&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#8aadf4&#34;&gt;.word&lt;/span&gt;   &lt;span style=&#34;color:#eed49f&#34;&gt;hard_fault_handler&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#8aadf4&#34;&gt;.word&lt;/span&gt;   &lt;span style=&#34;color:#f5a97f&#34;&gt;0&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//not in M0+
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#8aadf4&#34;&gt;.word&lt;/span&gt;   &lt;span style=&#34;color:#f5a97f&#34;&gt;0&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//not in M0+
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#8aadf4&#34;&gt;.word&lt;/span&gt;   &lt;span style=&#34;color:#f5a97f&#34;&gt;0&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//not in M0+
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#8aadf4&#34;&gt;.word&lt;/span&gt;   &lt;span style=&#34;color:#f5a97f&#34;&gt;0&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//not in M0+
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#8aadf4&#34;&gt;.word&lt;/span&gt;   &lt;span style=&#34;color:#f5a97f&#34;&gt;0&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//not in M0+
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#8aadf4&#34;&gt;.word&lt;/span&gt;   &lt;span style=&#34;color:#f5a97f&#34;&gt;0&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//not in M0+
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#8aadf4&#34;&gt;.word&lt;/span&gt;   &lt;span style=&#34;color:#f5a97f&#34;&gt;0&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//not in M0+
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#8aadf4&#34;&gt;.word&lt;/span&gt;   &lt;span style=&#34;color:#eed49f&#34;&gt;svc_handler&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#8aadf4&#34;&gt;.word&lt;/span&gt;   &lt;span style=&#34;color:#f5a97f&#34;&gt;0&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//not in M0+
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#8aadf4&#34;&gt;.word&lt;/span&gt;   &lt;span style=&#34;color:#f5a97f&#34;&gt;0&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//not in M0+
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#8aadf4&#34;&gt;.word&lt;/span&gt;   &lt;span style=&#34;color:#eed49f&#34;&gt;pendsv_handler&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#8aadf4&#34;&gt;.word&lt;/span&gt;   &lt;span style=&#34;color:#eed49f&#34;&gt;systick_handler&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//-------------- peripherals list
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#8aadf4&#34;&gt;.word&lt;/span&gt;   &lt;span style=&#34;color:#eed49f&#34;&gt;PM_Handler&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#8aadf4&#34;&gt;.word&lt;/span&gt;   &lt;span style=&#34;color:#eed49f&#34;&gt;SYSCTRL_Handler&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#8aadf4&#34;&gt;.word&lt;/span&gt;   &lt;span style=&#34;color:#eed49f&#34;&gt;WDT_Handler&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#8aadf4&#34;&gt;.word&lt;/span&gt;   &lt;span style=&#34;color:#eed49f&#34;&gt;RTC_Handler&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#8aadf4&#34;&gt;.word&lt;/span&gt;   &lt;span style=&#34;color:#eed49f&#34;&gt;EIC_Handler&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#8aadf4&#34;&gt;.word&lt;/span&gt;   &lt;span style=&#34;color:#eed49f&#34;&gt;NVMCTRL_Handler&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#8aadf4&#34;&gt;.word&lt;/span&gt;   &lt;span style=&#34;color:#eed49f&#34;&gt;DMAC_Handler&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#8aadf4&#34;&gt;.word&lt;/span&gt;   &lt;span style=&#34;color:#eed49f&#34;&gt;USB_Handler&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#8aadf4&#34;&gt;.word&lt;/span&gt;   &lt;span style=&#34;color:#eed49f&#34;&gt;EVSYS_Handler&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#8aadf4&#34;&gt;.word&lt;/span&gt;   &lt;span style=&#34;color:#eed49f&#34;&gt;SERCOM0_Handler&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#8aadf4&#34;&gt;.word&lt;/span&gt;   &lt;span style=&#34;color:#eed49f&#34;&gt;SERCOM1_Handler&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#8aadf4&#34;&gt;.word&lt;/span&gt;   &lt;span style=&#34;color:#eed49f&#34;&gt;SERCOM2_Handler&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#8aadf4&#34;&gt;.word&lt;/span&gt;   &lt;span style=&#34;color:#eed49f&#34;&gt;SERCOM3_Handler&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#8aadf4&#34;&gt;.word&lt;/span&gt;   &lt;span style=&#34;color:#f5a97f&#34;&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#8aadf4&#34;&gt;.word&lt;/span&gt;   &lt;span style=&#34;color:#f5a97f&#34;&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#8aadf4&#34;&gt;.word&lt;/span&gt;   &lt;span style=&#34;color:#eed49f&#34;&gt;TCC0_Handler&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#8aadf4&#34;&gt;.word&lt;/span&gt;   &lt;span style=&#34;color:#eed49f&#34;&gt;TCC1_Handler&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#8aadf4&#34;&gt;.word&lt;/span&gt;   &lt;span style=&#34;color:#eed49f&#34;&gt;TCC2_Handler&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#8aadf4&#34;&gt;.word&lt;/span&gt;   &lt;span style=&#34;color:#eed49f&#34;&gt;TC3_Handler&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#8aadf4&#34;&gt;.word&lt;/span&gt;   &lt;span style=&#34;color:#eed49f&#34;&gt;TC4_Handler&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#8aadf4&#34;&gt;.word&lt;/span&gt;   &lt;span style=&#34;color:#eed49f&#34;&gt;TC5_Handler&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#8aadf4&#34;&gt;.word&lt;/span&gt;   &lt;span style=&#34;color:#f5a97f&#34;&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#8aadf4&#34;&gt;.word&lt;/span&gt;   &lt;span style=&#34;color:#f5a97f&#34;&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#8aadf4&#34;&gt;.word&lt;/span&gt;   &lt;span style=&#34;color:#eed49f&#34;&gt;ADC_Handler&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#8aadf4&#34;&gt;.word&lt;/span&gt;   &lt;span style=&#34;color:#eed49f&#34;&gt;AC_Handler&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#8aadf4&#34;&gt;.word&lt;/span&gt;   &lt;span style=&#34;color:#eed49f&#34;&gt;DAC_Handler&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#8aadf4&#34;&gt;.word&lt;/span&gt;   &lt;span style=&#34;color:#eed49f&#34;&gt;PTC_Handler&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#8aadf4&#34;&gt;.word&lt;/span&gt;   &lt;span style=&#34;color:#eed49f&#34;&gt;I2S_Handler&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#8aadf4&#34;&gt;.word&lt;/span&gt;   &lt;span style=&#34;color:#f5a97f&#34;&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#8aadf4&#34;&gt;.word&lt;/span&gt;   &lt;span style=&#34;color:#f5a97f&#34;&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;.text&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;.section&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;.text.default_handler&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;.word&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;default_handler&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;.thumb_func&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#91d7e3&#34;&gt;default_handler:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   &lt;span style=&#34;color:#8aadf4&#34;&gt;ldr&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;r3&lt;/span&gt;, &lt;span style=&#34;color:#ed8796&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#0x8BADF00D
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;   &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//hangs the program.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;   &lt;span style=&#34;color:#8aadf4&#34;&gt;b&lt;/span&gt; .
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;.weakref&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;nmi_handler&lt;/span&gt;, &lt;span style=&#34;color:#eed49f&#34;&gt;default_handler&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;.weakref&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;hard_fault_handler&lt;/span&gt;, &lt;span style=&#34;color:#eed49f&#34;&gt;default_handler&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;.weakref&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;svc_handler&lt;/span&gt;, &lt;span style=&#34;color:#eed49f&#34;&gt;default_handler&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;.weakref&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;pendsv_handler&lt;/span&gt;, &lt;span style=&#34;color:#eed49f&#34;&gt;default_handler&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;.weakref&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;systick_handler&lt;/span&gt;, &lt;span style=&#34;color:#eed49f&#34;&gt;default_handler&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;.weakref&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;PM_Handler&lt;/span&gt;, &lt;span style=&#34;color:#eed49f&#34;&gt;default_handler&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;.weakref&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;SYSCTRL_Handler&lt;/span&gt;, &lt;span style=&#34;color:#eed49f&#34;&gt;default_handler&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;.weakref&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;WDT_Handler&lt;/span&gt;, &lt;span style=&#34;color:#eed49f&#34;&gt;default_handler&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;.weakref&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;RTC_Handler&lt;/span&gt;, &lt;span style=&#34;color:#eed49f&#34;&gt;default_handler&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;.weakref&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;EIC_Handler&lt;/span&gt;, &lt;span style=&#34;color:#eed49f&#34;&gt;default_handler&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;.weakref&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;NVMCTRL_Handler&lt;/span&gt;, &lt;span style=&#34;color:#eed49f&#34;&gt;default_handler&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;.weakref&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;DMAC_Handler&lt;/span&gt;, &lt;span style=&#34;color:#eed49f&#34;&gt;default_handler&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;.weakref&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;USB_Handler&lt;/span&gt;, &lt;span style=&#34;color:#eed49f&#34;&gt;default_handler&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;.weakref&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;EVSYS_Handler&lt;/span&gt;, &lt;span style=&#34;color:#eed49f&#34;&gt;default_handler&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;.weakref&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;SERCOM0_Handler&lt;/span&gt;, &lt;span style=&#34;color:#eed49f&#34;&gt;default_handler&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;.weakref&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;SERCOM1_Handler&lt;/span&gt;, &lt;span style=&#34;color:#eed49f&#34;&gt;default_handler&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;.weakref&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;SERCOM2_Handler&lt;/span&gt;, &lt;span style=&#34;color:#eed49f&#34;&gt;default_handler&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;.weakref&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;SERCOM3_Handler&lt;/span&gt;, &lt;span style=&#34;color:#eed49f&#34;&gt;default_handler&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//.weakref SERCOM4_Handler, default_handler
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//.weakref SERCOM5_Handler, default_handler
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;.weakref&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;TCC0_Handler&lt;/span&gt;, &lt;span style=&#34;color:#eed49f&#34;&gt;default_handler&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;.weakref&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;TCC1_Handler&lt;/span&gt;, &lt;span style=&#34;color:#eed49f&#34;&gt;default_handler&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;.weakref&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;TCC2_Handler&lt;/span&gt;, &lt;span style=&#34;color:#eed49f&#34;&gt;default_handler&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;.weakref&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;TC3_Handler&lt;/span&gt;, &lt;span style=&#34;color:#eed49f&#34;&gt;default_handler&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;.weakref&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;TC4_Handler&lt;/span&gt;, &lt;span style=&#34;color:#eed49f&#34;&gt;default_handler&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;.weakref&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;TC5_Handler&lt;/span&gt;, &lt;span style=&#34;color:#eed49f&#34;&gt;default_handler&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//.weakref TC6_Handler, default_handler
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//.weakref TC7_Handler, default_handler
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;.weakref&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;ADC_Handler&lt;/span&gt;, &lt;span style=&#34;color:#eed49f&#34;&gt;default_handler&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;.weakref&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;AC_Handler&lt;/span&gt;, &lt;span style=&#34;color:#eed49f&#34;&gt;default_handler&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;.weakref&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;DAC_Handler&lt;/span&gt;, &lt;span style=&#34;color:#eed49f&#34;&gt;default_handler&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;.weakref&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;PTC_Handler&lt;/span&gt;, &lt;span style=&#34;color:#eed49f&#34;&gt;default_handler&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;.weakref&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;I2S_Handler&lt;/span&gt;, &lt;span style=&#34;color:#eed49f&#34;&gt;default_handler&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;.weakref&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;AC1_Handler&lt;/span&gt;, &lt;span style=&#34;color:#eed49f&#34;&gt;default_handler&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//.weakref TCC3_Handler, default_handler
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;summary&#34;&gt;Summary&lt;/h2&gt;
&lt;p&gt;I already have a WIP with all the peripherals commented, a better default handler, etc. But I think this post is quite long enough!&lt;/p&gt;
&lt;p&gt;Hopefully, fingers crossed, next time, blinking?&lt;/p&gt;
</description>
    </item>
    
    
    
    <item>
      <title>How can I make programming an ARM chip as hard as possible?</title>
      <link>https://whynotestflight.com/excuses/how-can-i-make-programming-an-arm-chip-as-hard-as-possible/</link>
      <pubDate>Sat, 06 Apr 2024 00:00:00 +0000</pubDate>
      
      <guid>https://whynotestflight.com/excuses/how-can-i-make-programming-an-arm-chip-as-hard-as-possible/</guid>
      <description>&lt;p&gt;Related Repo: &lt;a href=&#34;https://github.com/carlynorama/StrippedDownChipRosetta&#34;&gt;https://github.com/carlynorama/StrippedDownChipRosetta&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Historically chip companies have designed and manufactured their own chips. Switching to a different manufacturer meant changing everything, software to board.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://developer.arm.com/documentation&#34;&gt;Arm&lt;/a&gt; changed that by licensing their designs and instruction sets to more than one manufacturer.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;44 min &lt;a href=&#34;https://www.youtube.com/watch?v=7LqPJGnBPMM&#34;&gt;video overview&lt;/a&gt; of the architecture and ecosystem put out by Arm&lt;/li&gt;
&lt;li&gt;13 min &lt;a href=&#34;https://www.youtube.com/watch?v=1jOJl8gRPyQ&#34;&gt;Interview with Prof. Furber&lt;/a&gt; by Computerphile&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;With so many to choose from, I&amp;rsquo;m going to go with the Arm chip that reminds me the most of the ATtiny - Microchip&amp;rsquo;s (Atmel) SAMD21 family. (Also - We have A LOT of &lt;a href=&#34;https://www.adafruit.com/product/3500&#34;&gt;Trinket M0&lt;/a&gt;&amp;rsquo;s in the house)&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://www.microchip.com/en-us/product/ATSAMD21E18&#34;&gt;Product Reference Page&lt;/a&gt; (has application notes)&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://ww1.microchip.com/downloads/aemDocuments/documents/MCU32/ProductDocuments/DataSheets/SAM-D21-DA1-Family-Data-Sheet-DS40001882H.pdf&#34;&gt;Full Data Sheet&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;Especially Section 10: Memories pg 41&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;http://ww1.microchip.com/downloads/en/DeviceDoc/40001884A.pdf&#34;&gt;Summary Data Sheet&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;Especially Figure 9-1. SAM D21 Product Mapping&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;About Core M0 chips (ARMv6-M)
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://www.arm.com/products/silicon-ip-cpu/cortex-m/cortex-m0-plus&#34;&gt;https://www.arm.com/products/silicon-ip-cpu/cortex-m/cortex-m0-plus&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://en.wikipedia.org/wiki/ARM_Cortex-M&#34;&gt;https://en.wikipedia.org/wiki/ARM_Cortex-M&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://ww1.microchip.com/downloads/aemDocuments/documents/MCU32/ProductDocuments/Brochures/32-bit-Quick-Reference-Guide-60001455.pdf&#34;&gt;Peripheral Comparison Chart&lt;/a&gt; for Microchip 32-Bit chips&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;whats-the-first-step&#34;&gt;What&amp;rsquo;s the First Step?&lt;/h3&gt;
&lt;p&gt;Embedded Swift isn&amp;rsquo;t an &lt;a href=&#34;https://www.arduino.cc&#34;&gt;Arduino&lt;/a&gt; replacement. It&amp;rsquo;s gunning to be pretty low level. Documenting how to load an assembly program on to the chip with the GNU tool chain provides a solid reference base for then showing what it takes to switch over to the C from the assembly. Adding Embedded Swift to the mix will hopefully feel like just another think to add to a Makefile&amp;hellip;errr&amp;hellip; Cmake&amp;hellip;file.&lt;/p&gt;
&lt;p&gt;I don&amp;rsquo;t love it, but &amp;ldquo;bare metal&amp;rdquo; has become a trendy term in programming these days.  Like calling a product &amp;ldquo;green&amp;rdquo;, there&amp;rsquo;s no precise definition as to what it means. While environments without an operating system may have more of claim than dockerless servers, even within that context people differ in how they use it.  In general it means the author will be trading expedience for control, so it can be a useful search term. That said, when known, use:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;actual part numbers&lt;/li&gt;
&lt;li&gt;software package names&lt;/li&gt;
&lt;li&gt;chip family names&lt;/li&gt;
&lt;li&gt;language names&lt;/li&gt;
&lt;li&gt;code snippets&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Using these I still got results with &amp;ldquo;bare metal&amp;rdquo; in the title! Ha! My top instructional resources that contributed to this page and will help it make more sense:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;This post essentially implements the following tutorial using a different chip (SAMD21E18 vs STM32-F031K6) and a different programming toolchain (OpenOCD vs STLink).
&lt;ul&gt;
&lt;li&gt;article: &lt;a href=&#34;https://vivonomicon.com/2018/04/02/bare-metal-stm32-programming-part-1-hello-arm/&#34;&gt;https://vivonomicon.com/2018/04/02/bare-metal-stm32-programming-part-1-hello-arm/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;repo: &lt;a href=&#34;https://github.com/WRansohoff/STM32F0_minimal&#34;&gt;https://github.com/WRansohoff/STM32F0_minimal&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;STM32 Based Fastbit Embedded Brain Academy &amp;ldquo;Bare metal embedded&amp;rdquo; playlist. No-library C based. Incredibly thorough review of how the software interacts with the hardware. A++. (Windows, but since GNU command line tools doesn&amp;rsquo;t matter.)
&lt;ul&gt;
&lt;li&gt;playlist: &lt;a href=&#34;https://www.youtube.com/watch?v=qWqlkCLmZoE&amp;amp;list=PLERTijJOmYrDiiWd10iRHY0VRHdJwUH4g&#34;&gt;https://www.youtube.com/watch?v=qWqlkCLmZoE&amp;amp;list=PLERTijJOmYrDiiWd10iRHY0VRHdJwUH4g&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;repo: &lt;a href=&#34;https://github.com/niekiran/baremetalembedded&#34;&gt;https://github.com/niekiran/baremetalembedded&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;I stole his programmer, he told me about OpenOCD, recently updated: &lt;a href=&#34;https://github.com/todbot/samd21-programming-notes&#34;&gt;https://github.com/todbot/samd21-programming-notes&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;The product I&amp;rsquo;m using, but the Metro M4 would be a better choice if shopping. Shows the CircuitPython path: &lt;a href=&#34;https://learn.adafruit.com/adafruit-pyruler/downloads&#34;&gt;https://learn.adafruit.com/adafruit-pyruler/downloads&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Has a a good chip overview and overall a much more reasonable Arduino based start up process with a better board than my example: &lt;a href=&#34;https://learn.sparkfun.com/tutorials/samd21-minidev-breakout-hookup-guide/all#samd21-overview&#34;&gt;https://learn.sparkfun.com/tutorials/samd21-minidev-breakout-hookup-guide/all#samd21-overview&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Epic linker script with a ton of further reading, other SAMD21 information on the blog
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://blog.thea.codes/the-most-thoroughly-commented-linker-script/&#34;&gt;https://blog.thea.codes/the-most-thoroughly-commented-linker-script/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/wntrblm/Castor_and_Pollux/blob/main/firmware/scripts/samd21g18a.ld&#34;&gt;https://github.com/wntrblm/Castor_and_Pollux/blob/main/firmware/scripts/samd21g18a.ld&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Using OpenOCD: &lt;a href=&#34;https://omzlo.com/articles/programming-the-samd21-using-atmel-ice-with-openocd-(updated)&#34;&gt;https://omzlo.com/articles/programming-the-samd21-using-atmel-ice-with-openocd-(updated)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Introduction to Assembly Programming with Arm - Nice overview but NOT .thumb mode needed for Coretex M0+. Uses an emulator for the first part but switches to a VM for the last part. Handy.
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://www.youtube.com/watch?v=in-UY_EyI14&amp;amp;list=PL2EF13wm-hWAlQe87UB2HV0SVhBXFpXbn&#34;&gt;https://www.youtube.com/watch?v=in-UY_EyI14&amp;amp;list=PL2EF13wm-hWAlQe87UB2HV0SVhBXFpXbn&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://cpulator.01xz.net&#34;&gt;https://cpulator.01xz.net&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;TODO: I&amp;rsquo;ve got a giant notes page with even more links that needs to be organized.&lt;/p&gt;
&lt;h2 id=&#34;which-programmer&#34;&gt;Which Programmer?&lt;/h2&gt;
&lt;p&gt;I love the UF2 (USB Flashing Format) programming method which allows &lt;a href=&#34;https://github.com/adafruit/tinyuf2&#34;&gt;many boards&lt;/a&gt; to be programmed via USB, no programmer needed.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://makecode.com/blog/one-chip-to-flash-them-all&#34;&gt;2017 makecode blog post&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://microsoft.github.io/uf2/&#34;&gt;USB Flashing Format (UF2)&lt;/a&gt; explanation from microsoft.github.io&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This post will not use that feature.&lt;/p&gt;
&lt;p&gt;I would like the first couple of examples to be as close as possible to the &lt;a href=&#34;https://whynotestflight.com/excuses/hello-led-on-an-avr-attiny45-in-c/&#34;&gt;AVR process&lt;/a&gt; which means programming via a programmer, not USB.&lt;/p&gt;
&lt;p&gt;The role of &lt;a href=&#34;https://github.com/avrdudes/avrdude&#34;&gt;AVRDude&lt;/a&gt; will be played by &lt;a href=&#34;https://openocd.org&#34;&gt;OpenOCD&lt;/a&gt; software. OCD stands for &amp;ldquo;On Chip Debugger&amp;rdquo; so it&amp;rsquo;s not exactly a 1 to 1 swap. Also install the &lt;a href=&#34;https://developer.arm.com/Tools%20and%20Software/GNU%20Toolchain&#34;&gt;gnu gcc arm toolchain&lt;/a&gt; because it has the version of GDB that we need.&lt;/p&gt;
&lt;p&gt;To install on MacOS&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## this is the cross compiler version&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## installs from https://developer.arm.com/Tools%20and%20Software/GNU%20Toolchain&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## see https://formulae.brew.sh/cask/gcc-arm-embedded#default&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## the below command worked for me in 4/2024&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## if it doesn&amp;#39;t work for you try &amp;#34;brew install --cask gcc-arm-embedded&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;brew install gcc-arm-embedded  
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;arm-none-eabi-gcc --help
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;brew install openocd
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## confirm install see options&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;openocd --help
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## Optional&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## if want to use openocd in telnet mode&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;brew install telnet
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;There are &lt;a href=&#34;https://openocd.org/pages/supported-jtag-interfaces.html&#34;&gt;MANY programmers&lt;/a&gt; that will work with OpenOCD. Anything implementing &lt;a href=&#34;https://en.wikipedia.org/wiki/JTAG&#34;&gt;JTAG&lt;/a&gt; (Joint Test Action Group), really.&lt;/p&gt;
&lt;p&gt;Since the SAMD21D has so few pins, the Trinket exposes the &lt;a href=&#34;https://en.wikipedia.org/wiki/JTAG#Similar_interface_standards&#34;&gt;SWD&lt;/a&gt; (Serial Wire Debug) interface instead of JTAG. The following programmers can work with it (~INT = ball park price in US dollars). The first -three- four I have seen in action personally.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://www.segger.com/products/debug-probes/j-link/models/j-link-edu/&#34;&gt;Segger JLink EDU edition&lt;/a&gt; (this post, ~150, pro is ~1k &lt;a href=&#34;https://www.segger.com/products/debug-probes/j-link/#c216543&#34;&gt;comparison guide&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://www.microchip.com/en-us/development-tool/atatmel-ice&#34;&gt;Atmel ICE&lt;/a&gt; (~200, &lt;a href=&#34;https://arm-software.github.io/CMSIS-DAP/latest/index.html&#34;&gt;CMSIS-DAP&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://www.st.com/en/development-tools/st-link-v2.html&#34;&gt;ST-Link&lt;/a&gt; (V2 around ~23, V2-ISOL ~90)&lt;/li&gt;
&lt;li&gt;New! todbot just got a &lt;a href=&#34;https://daplink.io&#34;&gt;DapLink&lt;/a&gt; compatible programmer from &lt;a href=&#34;https://www.amazon.com/s?k=daplink&amp;amp;language=en_US&amp;amp;crid=LWU5XBTTK50W&amp;amp;linkCode=sl2&amp;amp;linkId=e6a665f7b343f7e5cb4bca6e47821fbf&amp;amp;sprefix=daplin%2Caps%2C201&amp;amp;tag=todbotblog-20&amp;amp;ref=as_li_ss_tl&#34;&gt;Amazon&lt;/a&gt; and confirmed it worked. (specifically &lt;a href=&#34;https://amzn.to/4aL3cas&#34;&gt;this one&lt;/a&gt;, requires soldering ~8) (affiliate links heads up. I made him.) (&lt;a href=&#34;https://github.com/ARMmbed/mbed-hdk&#34;&gt;PLANS&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://www.segger.com/products/debug-probes/j-link/models/j-link-edu-mini/&#34;&gt;Segger JLink EDU mini&lt;/a&gt; (~60)&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://www.raspberrypi.com/documentation/microcontrollers/debug-probe.html&#34;&gt;Raspberry pi debug probe&lt;/a&gt; (~12)&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://black-magic.org&#34;&gt;Black Magic Probe&lt;/a&gt; (~75)&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://oshwlab.com/wagiminator/samd11c-swd-programmer&#34;&gt;SAMD11C SWD Programmer Stick&lt;/a&gt; PLANS ONLY! (&lt;a href=&#34;https://github.com/wagiminator/SAMD-Development-Boards/tree/main/SWD_Programmer_Stick&#34;&gt;repo&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://hackaday.com/2021/07/01/esp32-turned-handy-swd-flasher-for-nrf52-chips/&#34;&gt;ESP32 Wifi Debugger&lt;/a&gt; PLANS ONLY (&lt;a href=&#34;https://github.com/atc1441/ESP32_nRF52_SWD&#34;&gt;repo&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://mtm.cba.mit.edu/2021/2021-10_microcontroller-primer/tools-cmsis-dap/&#34;&gt;MIT Machines That Make open source design&lt;/a&gt; PLANS ONLY&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;prep-the-board--programmer&#34;&gt;Prep the Board &amp;amp; Programmer&lt;/h2&gt;
&lt;p&gt;I&amp;rsquo;ve appropriated a &lt;a href=&#34;https://www.adafruit.com/product/4319&#34;&gt;PyRuler&lt;/a&gt; I&amp;rsquo;ve had on the shelf for awhile. It has a lot going on around the Trinket.  They are super fun. If I was going to actually buy something for this task, I would buy something with a SWD or JTAG connection that was ready to go. When shopping you might see boards with a place for the &lt;a href=&#34;https://www.tag-connect.com&#34;&gt;tag-connect&lt;/a&gt;, but you&amp;rsquo;ll &lt;a href=&#34;https://www.tag-connect.com/debugger-cable-selection-installation-instructions&#34;&gt;need a special cable&lt;/a&gt; for your debugger.&lt;/p&gt;
&lt;p&gt;Trinkets &lt;a href=&#34;https://learn.adafruit.com/adafruit-trinket-m0-circuitpython-arduino/pinouts#secret-swd-pads-2910533&#34;&gt;expose the pads&lt;/a&gt;, but you have to solder to them or design a jig. (Looking forward to putting the UF2 bootloader back on&amp;hellip;)&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://www.segger.com/products/debug-probes/j-link/technology/interface-description/#jtag-interface-connection-20-pin&#34;&gt;https://www.segger.com/products/debug-probes/j-link/technology/interface-description/#jtag-interface-connection-20-pin&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://learn.adafruit.com/adafruit-trinket-m0-circuitpython-arduino/pinouts&#34;&gt;https://learn.adafruit.com/adafruit-trinket-m0-circuitpython-arduino/pinouts&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://learn.adafruit.com/how-to-program-samd-bootloaders/trinket-m0-wiring&#34;&gt;https://learn.adafruit.com/how-to-program-samd-bootloaders/trinket-m0-wiring&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Reset pin notes: The PyRuler &lt;a href=&#34;https://learn.adafruit.com/assets/78957&#34;&gt;does not overload the SWD pads&lt;/a&gt; (PA31, PA31) so setting up the reset pin &lt;a href=&#34;https://electronics.stackexchange.com/questions/86418/relationship-between-reset-pins-and-swd-functions-arm-cortex-m0&#34;&gt;may not be needed or useful&lt;/a&gt; for your set up.&lt;/p&gt;
&lt;table&gt;
  &lt;thead&gt;
      &lt;tr&gt;
          &lt;th style=&#34;text-align: left&#34;&gt;Programmer&lt;/th&gt;
          &lt;th style=&#34;text-align: left&#34;&gt;Trinket&lt;/th&gt;
          &lt;th style=&#34;text-align: left&#34;&gt;Wire Color&lt;/th&gt;
      &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
      &lt;tr&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;1 VTref&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;3V&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;brown&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;7 SWDIO&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;pad further from usb edge&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;blue&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;9 SWCLCK&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;pad closer to usb edge&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;yellow&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;15 RESET&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;RESET&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;green&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;19 5V-Supply*&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;BAT&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;red&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;18 GND&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;GND&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;black&lt;/td&gt;
      &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;ul&gt;
&lt;li&gt;The 5V-Supply/red wire in theory could be used to power the board. But I haven&amp;rsquo;t &lt;a href=&#34;https://sourceforge.net/p/openocd/mailman/openocd-devel/thread/D346A023-5B99-41F2-A6BB-A746ECE25A40%40onethinx.com/&#34;&gt;sorted the configuration&lt;/a&gt; yet, so I&amp;rsquo;m using USB for power. It&amp;rsquo;s attached in the pictures so it isn&amp;rsquo;t flapping in the breeze.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The &lt;a href=&#34;https://www.segger.com/products/debug-probes/j-link/technology/interface-description/#jtag-interface-connection-20-pin&#34;&gt;official pin&lt;/a&gt; out is from the point of view of looking down at a board&amp;rsquo;s connector, not AT the programmer&amp;rsquo;s connector. I&amp;rsquo;ve flipped this to make it look more like the picture.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;jlink_edu_SWD_flipped.svg&#34; alt=&#34;JLink SWD mode pinout&#34;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;trinket.png&#34; alt=&#34;Trinket Pinout Diagram&#34;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;IMG_1678.jpeg&#34; alt=&#34;JLink connector&#34;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;IMG_1672.jpeg&#34; alt=&#34;Closeup of my terrible soldering job&#34;&gt;&lt;/p&gt;
&lt;h2 id=&#34;talk-to-the-board&#34;&gt;Talk to the Board&lt;/h2&gt;
&lt;h3 id=&#34;config-file-and-start-up&#34;&gt;Config File and Start Up&lt;/h3&gt;
&lt;p&gt;OpenOCD requires .cfg files for programmers, boards and chips. Since we have a single chip board we only need two config files, but we write one config file that can find them both for us.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/openocd-org/openocd/tree/v0.6.1/tcl/interface&#34;&gt;https://github.com/openocd-org/openocd/tree/v0.6.1/tcl/interface&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/openocd-org/openocd/tree/v0.6.1/tcl/board&#34;&gt;https://github.com/openocd-org/openocd/tree/v0.6.1/tcl/board&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/openocd-org/openocd/tree/v0.6.1/tcl/target&#34;&gt;https://github.com/openocd-org/openocd/tree/v0.6.1/tcl/target&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The below is the minium viable config file. No commands. Nothing but the programmer and board info. Call it &lt;code&gt;openocd.cfg&lt;/code&gt;&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-openocd&#34; data-lang=&#34;openocd&#34;&gt;# Segger J-Link EDU, SWD mode
## adapter line same as 
# #source [find interface/jlink.cfg]
adapter driver jlink
transport select swd

# Chip info (pyruler trinket)
set CHIPNAME at91samd21e18
source [find target/at91samdXX.cfg]
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;From the directory with this file running the bare &lt;code&gt;openocd&lt;/code&gt; command will start up the various local servers that openocd will manage for you (&lt;a href=&#34;https://sourceware.org/gdb/current/onlinedocs/gdb.html/Server.html#Server&#34;&gt;gdbserver&lt;/a&gt;, telnet and tcl).&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://openocd.org/doc-release/doxygen/index.html&#34;&gt;https://openocd.org/doc-release/doxygen/index.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://openocd.org/doc/html/OpenOCD-Project-Setup.html&#34;&gt;https://openocd.org/doc/html/OpenOCD-Project-Setup.html&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If one has more than one config file, you might want to call a specific one directly. Then openocd will want some direction about what you want to do with it.:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## init - necessary start up&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## targets - lists all attached chips&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## reset halt - puts chip in reset mode (i.e. in order to program, etc.)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;openocd -f ./YOUR_FILE_NAME.cfg -c &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#39;init; targets; reset halt;&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ul&gt;
&lt;li&gt;more commands: &lt;a href=&#34;https://openocd.org/doc/html/General-Commands.html&#34;&gt;https://openocd.org/doc/html/General-Commands.html&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Those commands could be in the .cfg file instead, and then you don&amp;rsquo;t need the -c part of the above command.&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-openocd&#34; data-lang=&#34;openocd&#34;&gt;# Segger J-Link EDU, SWD modere
## adapter line same as 
# #source [find interface/jlink.cfg]
adapter driver jlink
transport select swd

# Chip info (pyruler trinket)
set CHIPNAME at91samd21e18
source [find target/at91samdXX.cfg]

init
targets
reset halt
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The output with the first set up should look something like the below, but keep in mind my chip already has code on it. If you have trouble getting here, try putting your Trinket in reset mode by hand to start (double click the reset button).&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Open On-Chip Debugger 0.12.0
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Licensed under GNU GPL v2
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;For bug reports, &lt;span style=&#34;color:#91d7e3&#34;&gt;read&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        http://openocd.org/doc/doxygen/bugs.html
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Info : Listening on port &lt;span style=&#34;color:#f5a97f&#34;&gt;6666&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;for&lt;/span&gt; tcl connections
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Info : Listening on port &lt;span style=&#34;color:#f5a97f&#34;&gt;4444&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;for&lt;/span&gt; telnet connections
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Info : J-Link V9 compiled Dec &lt;span style=&#34;color:#f5a97f&#34;&gt;13&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;2019&lt;/span&gt; 11:14:50
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Info : Hardware version: 9.20
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Info : &lt;span style=&#34;color:#f4dbd6&#34;&gt;VTarget&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; 3.325 V
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Info : clock speed &lt;span style=&#34;color:#f5a97f&#34;&gt;400&lt;/span&gt; kHz
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Info : SWD DPIDR 0x0bc11477 &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# &amp;lt;-- common place to fail&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Info : &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;[&lt;/span&gt;at91samd21e18.cpu&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;]&lt;/span&gt; Cortex-M0+ r0p1 processor detected
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Info : &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;[&lt;/span&gt;at91samd21e18.cpu&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;]&lt;/span&gt; target has &lt;span style=&#34;color:#f5a97f&#34;&gt;4&lt;/span&gt; breakpoints, &lt;span style=&#34;color:#f5a97f&#34;&gt;2&lt;/span&gt; watchpoints
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Info : starting gdb server &lt;span style=&#34;color:#c6a0f6&#34;&gt;for&lt;/span&gt; at91samd21e18.cpu on &lt;span style=&#34;color:#f5a97f&#34;&gt;3333&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Info : Listening on port &lt;span style=&#34;color:#f5a97f&#34;&gt;3333&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;for&lt;/span&gt; gdb connections
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;telnet-mode&#34;&gt;Telnet Mode&lt;/h3&gt;
&lt;p&gt;Notice that OpenOCD is &lt;code&gt;Listening on port 4444 for telnet connections&lt;/code&gt; that&amp;rsquo;s for people. If one wants to write automation that&amp;rsquo;s what the &lt;a href=&#34;https://en.wikipedia.org/wiki/Tcl&#34;&gt;tcl&lt;/a&gt; option on port 6666 is for. Those &lt;a href=&#34;https://openocd.org/doc/html/Server-Configuration.html&#34;&gt;port numbers can be changed&lt;/a&gt; via the config file.&lt;/p&gt;
&lt;p&gt;In a separate shell try:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-zsh&#34; data-lang=&#34;zsh&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;telnet localhost &lt;span style=&#34;color:#f5a97f&#34;&gt;4444&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# ... once connected&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;gt; reset
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;gt; targets
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;gt; reg
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;reset&lt;/code&gt; gets the board out of reset mode. &lt;code&gt;targets&lt;/code&gt; was covered above and the &lt;a href=&#34;https://openocd.org/doc/html/General-Commands.html&#34;&gt;reg command&lt;/a&gt; will print out all the values of the registers.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;gt; targets
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    TargetName         Type       Endian TapName            State       
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;--  ------------------ ---------- ------ ------------------ ------------
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; 0* at91samd21e18.cpu  cortex_m   little at91samd21e18.cpu  running
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;gt; reg
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## If no values, try again when in debug mode&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=====&lt;/span&gt; arm v7m registers
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;(&lt;/span&gt;0&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;)&lt;/span&gt; r0 &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;(&lt;/span&gt;/32&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;)&lt;/span&gt;: 0x00003200
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;(&lt;/span&gt;1&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;)&lt;/span&gt; r1 &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;(&lt;/span&gt;/32&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;)&lt;/span&gt;: 0x00000000
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;(&lt;/span&gt;2&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;)&lt;/span&gt; r2 &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;(&lt;/span&gt;/32&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;)&lt;/span&gt;: 0x00000000
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;(&lt;/span&gt;3&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;)&lt;/span&gt; r3 &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;(&lt;/span&gt;/32&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;)&lt;/span&gt;: 0x0000131a
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;(&lt;/span&gt;4&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;)&lt;/span&gt; r4 &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;(&lt;/span&gt;/32&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;)&lt;/span&gt;: 0x00400040
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;(&lt;/span&gt;5&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;)&lt;/span&gt; r5 &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;(&lt;/span&gt;/32&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;)&lt;/span&gt;: 0xe000ed00
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;(&lt;/span&gt;6&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;)&lt;/span&gt; r6 &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;(&lt;/span&gt;/32&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;)&lt;/span&gt;: 0x00000005
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;(&lt;/span&gt;7&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;)&lt;/span&gt; r7 &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;(&lt;/span&gt;/32&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;)&lt;/span&gt;: 0x20002db0
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;(&lt;/span&gt;8&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;)&lt;/span&gt; r8 &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;(&lt;/span&gt;/32&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;)&lt;/span&gt;: 0x7afff4ef
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;(&lt;/span&gt;9&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;)&lt;/span&gt; r9 &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;(&lt;/span&gt;/32&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;)&lt;/span&gt;: 0xdde5fa1f
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;(&lt;/span&gt;10&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;)&lt;/span&gt; r10 &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;(&lt;/span&gt;/32&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;)&lt;/span&gt;: 0x27f9bfba
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;(&lt;/span&gt;11&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;)&lt;/span&gt; r11 &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;(&lt;/span&gt;/32&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;)&lt;/span&gt;: 0xefedfdff
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;(&lt;/span&gt;12&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;)&lt;/span&gt; r12 &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;(&lt;/span&gt;/32&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;)&lt;/span&gt;: 0xb9e9f4ff
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;(&lt;/span&gt;13&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;)&lt;/span&gt; sp &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;(&lt;/span&gt;/32&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;)&lt;/span&gt;: 0x20002dd8
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;(&lt;/span&gt;14&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;)&lt;/span&gt; lr &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;(&lt;/span&gt;/32&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;)&lt;/span&gt;: 0x00000527
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;(&lt;/span&gt;15&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;)&lt;/span&gt; pc &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;(&lt;/span&gt;/32&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;)&lt;/span&gt;: 0x00000288
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;(&lt;/span&gt;16&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;)&lt;/span&gt; xPSR &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;(&lt;/span&gt;/32&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;)&lt;/span&gt;: 0x21000000
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;(&lt;/span&gt;17&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;)&lt;/span&gt; msp &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;(&lt;/span&gt;/32&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;)&lt;/span&gt;: 0x20002dd8
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;(&lt;/span&gt;18&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;)&lt;/span&gt; psp &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;(&lt;/span&gt;/32&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;)&lt;/span&gt;: 0xf63efff0
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;(&lt;/span&gt;20&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;)&lt;/span&gt; primask &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;(&lt;/span&gt;/1&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;)&lt;/span&gt;: 0x00
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;(&lt;/span&gt;21&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;)&lt;/span&gt; basepri &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;(&lt;/span&gt;/8&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;)&lt;/span&gt;: 0x00
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;(&lt;/span&gt;22&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;)&lt;/span&gt; faultmask &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;(&lt;/span&gt;/1&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;)&lt;/span&gt;: 0x00
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;(&lt;/span&gt;23&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;)&lt;/span&gt; control &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;(&lt;/span&gt;/3&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;)&lt;/span&gt;: &lt;span style=&#34;color:#f4dbd6&#34;&gt;0x00&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=====&lt;/span&gt; Cortex-M DWT registers
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;debugger-mode&#34;&gt;Debugger Mode&lt;/h3&gt;
&lt;p&gt;In yet another shell window, start up gdb, but tell it to run from the server that&amp;rsquo;s already going.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## iex - Execute GDB command before loading the inferior.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;arm-none-eabi-gdb -iex &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;target extended-remote localhost:3333&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This command will open gdb but push it straight over to the openocd host. Since in my case there&amp;rsquo;s no compiled file on the local machine I can give it to cross check (yet) many of the usual commands won&amp;rsquo;t work.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://sourceware.org/gdb/current/onlinedocs/gdb.html/Inferiors-Connections-and-Programs.html&#34;&gt;https://sourceware.org/gdb/current/onlinedocs/gdb.html/Inferiors-Connections-and-Programs.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://sourceware.org/gdb/current/onlinedocs/gdb.html/Connecting.html&#34;&gt;https://sourceware.org/gdb/current/onlinedocs/gdb.html/Connecting.html&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In the mean time these should:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;layout asm&lt;/code&gt; to see the assembly&lt;/li&gt;
&lt;li&gt;&lt;code&gt;show architecture&lt;/code&gt; current target architecture.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;help target&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;To be honest, I haven&amp;rsquo;t used gdb before this past week. It wasn&amp;rsquo;t a thing I thought I needed. So wrong. So. So. Wrong. I love it. (Even &lt;a href=&#34;https://docs.arduino.cc/software/ide-v2/tutorials/ide-v2-debugger/&#34;&gt;Arduino IDE 2&lt;/a&gt; has it now! I did not know!)&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ve got a lot to learn - reading list:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;YouTube: &lt;a href=&#34;https://www.youtube.com/watch?v=lOA3S1ZgG2I&amp;amp;list=PL2EF13wm-hWAlQe87UB2HV0SVhBXFpXbn&amp;amp;index=16&#34;&gt;Last video in assembly playlist&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;YouTube: Chris Bourke UNebraska &lt;a href=&#34;https://www.youtube.com/watch?v=bWH-nL7v5F4&#34;&gt;9.2 - Debugging - GDB Tutorial&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://sourceware.org/gdb/documentation/&#34;&gt;https://sourceware.org/gdb/documentation/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://www.cs.cmu.edu/~gilpin/tutorial/&#34;&gt;https://www.cs.cmu.edu/~gilpin/tutorial/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://jacobmossberg.se/posts/2017/01/17/use-gdb-on-arm-assembly-program.html&#34;&gt;https://jacobmossberg.se/posts/2017/01/17/use-gdb-on-arm-assembly-program.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://azeria-labs.com/debugging-with-gdb-introduction/&#34;&gt;https://azeria-labs.com/debugging-with-gdb-introduction/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://www.usna.edu/Users/cs/lmcdowel/courses/ic220/S22/labs/armIntro/assembly.html&#34;&gt;https://www.usna.edu/Users/cs/lmcdowel/courses/ic220/S22/labs/armIntro/assembly.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;http://cs107e.github.io/guides/gdb/&#34;&gt;http://cs107e.github.io/guides/gdb/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://beej.us/guide/bggdb/&#34;&gt;https://beej.us/guide/bggdb/&lt;/a&gt; from tutorial below&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;core_hellos-and-linker_hellold&#34;&gt;core_hello.S and linker_hello.ld&lt;/h2&gt;
&lt;p&gt;The below code is pretty much taken from the excellent &lt;a href=&#34;https://vivonomicon.com/2018/04/02/bare-metal-stm32-programming-part-1-hello-arm/&#34;&gt;Hello Arm example&lt;/a&gt;, but with the linker script edited and commented for the SAMD21E18.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;m not going to comment on them until the next post with a more complete example.  I don&amp;rsquo;t recommend editing them piecemeal. They work &lt;em&gt;because&lt;/em&gt; there&amp;rsquo;s almost nothing in them. Adding more with out adding ALL the needed more could end up being more trouble than just doing the full linker and chip specific start script. Next post!&lt;/p&gt;
&lt;p&gt;If you&amp;rsquo;ve never seen assembly or a linker script before I&amp;rsquo;d say do the following in this order:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;watch &lt;a href=&#34;https://www.youtube.com/watch?v=lOA3S1ZgG2I&#34;&gt;the assembly playlist&lt;/a&gt; (keep in mind, it&amp;rsquo;s not quite the same version, see below. )&lt;/li&gt;
&lt;li&gt;watch the &lt;a href=&#34;https://www.youtube.com/watch?v=qWqlkCLmZoE&amp;amp;list=PLERTijJOmYrDiiWd10iRHY0VRHdJwUH4g&#34;&gt;C based&lt;/a&gt; playlist because he covers a lot of using the compiler to learn&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://vivonomicon.com/2018/04/02/bare-metal-stm32-programming-part-1-hello-arm/&#34;&gt;Read the Vivonomicon tutorial&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;read stargirl&amp;rsquo;s &lt;a href=&#34;https://blog.thea.codes/the-most-thoroughly-commented-linker-script/&#34;&gt;commented linker&lt;/a&gt; script.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If coming from desktop Arm, the Coretex-M0+ class of chip uses the 16-bit Thumb instruction set (&lt;a href=&#34;https://www.youtube.com/watch?v=rsg_Krh-o1U&#34;&gt;video 7min&lt;/a&gt; | &lt;a href=&#34;https://en.wikipedia.org/wiki/ARM_architecture_family#Thumb&#34;&gt;wikipedia&lt;/a&gt;) It&amp;rsquo;s a little different.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-C&#34; data-lang=&#34;C&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// These instructions define attributes of our chip and
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// the assembly language we&amp;#39;ll use:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;.syntax unified
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;.cpu cortex&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;-&lt;/span&gt;m0
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;.fpu softvfp &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//The Cortex-M0 line has no floating-point hardware
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;.thumb  &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//name for the ARM Cortex-M instruction set
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// Global memory locations.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//don&amp;#39;t put anything above the fake vector table. 
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;.global vector_table 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;.global on_reset
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;/*
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt; * interupt vector table
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt; * Only the RAM boundry and reset handler are
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt; * included, for simplicity.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt; */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;.type vector_table, &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;%&lt;/span&gt;object
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#91d7e3&#34;&gt;vector_table&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    .word _estack
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    .word on_reset
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;.size vector_table, .&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;-&lt;/span&gt;vector_table
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;/*
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt; * The Reset Handler. 
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt; */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;.type on_reset, &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;%&lt;/span&gt;function
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#91d7e3&#34;&gt;on_reset&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// Set the stack pointer to the end of the stack.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;  &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// The &amp;#39;_estack&amp;#39; value is defined in the linker script.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;  LDR  r0, &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt;_estack
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  MOV  sp, r0
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// Set some dummy values. When we see these values
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;  &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// in our debugger, we&amp;#39;ll know that our program
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;  &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// is loaded on the chip and working.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;  LDR  r7, &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#f5a97f&#34;&gt;0xDEADBEEF&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  MOVS r0, &lt;span style=&#34;color:#ed8796&#34;&gt;#&lt;/span&gt;&lt;span style=&#34;color:#f5a97f&#34;&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#91d7e3&#34;&gt;main_loop&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// Add 1 to register &amp;#39;r0&amp;#39;.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;    ADDS r0, r0, &lt;span style=&#34;color:#ed8796&#34;&gt;#&lt;/span&gt;&lt;span style=&#34;color:#f5a97f&#34;&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// Loop back.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;    B    main_loop
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;.size on_reset, .&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;-&lt;/span&gt;on_reset
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And the linker&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;MEMORY {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;/* Syntax: name(attr): ORIGIN = int, LENGTH = int */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;/* attr is kindof like chmod */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;/* get values from chip data sheet: SAMD21 section 10.2 */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;/* only need to mentions the one you&amp;#39;ll use */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;/* also called CODE_MEMORY or ROM */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;/* NOT LEAVING ROOM FOR BOOTLOADER */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#8aadf4&#34;&gt;flash&lt;/span&gt;(rx)&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;:&lt;/span&gt; ORIGIN &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;0x00000000&lt;/span&gt;, LENGTH &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;0x00040000&lt;/span&gt; &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;/*256K*/&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;/* also called just RAM */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#8aadf4&#34;&gt;sram&lt;/span&gt;(rwx)&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;:&lt;/span&gt; ORIGIN &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;0x20000000&lt;/span&gt;, LENGTH &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;0x00008000&lt;/span&gt; &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;/*32K*/&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;/* end of the stack  See 9.1 in Summary Data sheet */&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;_estack     &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;ORIGIN&lt;/span&gt;(sram) &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;+&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;LENGTH&lt;/span&gt;(sram);    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;/* stack points to end of SRAM */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;compile-upload-debug&#34;&gt;Compile, Upload, Debug&lt;/h2&gt;
&lt;p&gt;First we use the tools to compile core_hello.S to core.o to main.elf in a way that should feel very familiar from the [AVR post]/excuses/hello-led-on-an-avr-attiny45-in-c/.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;WARNING: Don&amp;rsquo;t forget the -g flag! (need it for gdb later)&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;arm-none-eabi-gcc -x assembler-with-cpp -c -O0 -mcpu&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt;cortex-m0 -mthumb -Wall -g core_hello.S -o core.o
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;arm-none-eabi-gcc core.o -mcpu&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt;cortex-m0 -mthumb -Wall --specs&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt;nosys.specs -nostdlib -lgcc -T./linker_hello.ld -o main.elf
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;arm-none-eabi-nm main.elf
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Once we have the elf we can use openocd to load it on the the chip. I put the commands in another cfg file.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://openocd.org/doc/html/Flash-Programming.html&#34;&gt;https://openocd.org/doc/html/Flash-Programming.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://openocd.org/doc/html/Flash-Commands.html#program&#34;&gt;https://openocd.org/doc/html/Flash-Commands.html#program&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://openocd.org/doc/html/Flash-Commands.html#flashprogrammingcommands&#34;&gt;https://openocd.org/doc/html/Flash-Commands.html#flashprogrammingcommands&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://openocd.org/doc/html/GDB-and-OpenOCD.html#programmingusinggdb&#34;&gt;https://openocd.org/doc/html/GDB-and-OpenOCD.html#programmingusinggdb&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-openocd&#34; data-lang=&#34;openocd&#34;&gt;# Segger J-Link EDU, SWD mode
adapter driver jlink
transport select swd

# Chip info (pyruler trinket)
set CHIPNAME at91samd21e18
source [find target/at91samdXX.cfg]

init
reset halt
at91samd bootloader 0
program main.elf verify
&lt;/code&gt;&lt;/pre&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-zsh&#34; data-lang=&#34;zsh&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;openocd -f program_and_serve.cfg
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The resulting output:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Open On-Chip Debugger 0.12.0
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Licensed under GNU GPL v2
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;For bug reports, &lt;span style=&#34;color:#91d7e3&#34;&gt;read&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        http://openocd.org/doc/doxygen/bugs.html
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Info : J-Link V9 compiled Dec &lt;span style=&#34;color:#f5a97f&#34;&gt;13&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;2019&lt;/span&gt; 11:14:50
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Info : Hardware version: 9.20
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Info : &lt;span style=&#34;color:#f4dbd6&#34;&gt;VTarget&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; 3.327 V
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Info : clock speed &lt;span style=&#34;color:#f5a97f&#34;&gt;400&lt;/span&gt; kHz
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Info : SWD DPIDR 0x0bc11477
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Info : &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;[&lt;/span&gt;at91samd21e18.cpu&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;]&lt;/span&gt; Cortex-M0+ r0p1 processor detected
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Info : &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;[&lt;/span&gt;at91samd21e18.cpu&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;]&lt;/span&gt; target has &lt;span style=&#34;color:#f5a97f&#34;&gt;4&lt;/span&gt; breakpoints, &lt;span style=&#34;color:#f5a97f&#34;&gt;2&lt;/span&gt; watchpoints
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Info : starting gdb server &lt;span style=&#34;color:#c6a0f6&#34;&gt;for&lt;/span&gt; at91samd21e18.cpu on &lt;span style=&#34;color:#f5a97f&#34;&gt;3333&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Info : Listening on port &lt;span style=&#34;color:#f5a97f&#34;&gt;3333&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;for&lt;/span&gt; gdb connections
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;[&lt;/span&gt;at91samd21e18.cpu&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;]&lt;/span&gt; halted due to debug-request, current mode: Thread 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;xPSR: 0x61000000 pc: 0x00000008 msp: 0x20008000
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;[&lt;/span&gt;at91samd21e18.cpu&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;]&lt;/span&gt; halted due to debug-request, current mode: Thread 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;xPSR: 0x61000000 pc: 0x00000008 msp: 0x20008000
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;** Programming Started **
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Info : SAMD MCU: SAMD21E18A &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;(&lt;/span&gt;256KB Flash, 32KB RAM&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;** Programming Finished **
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;** Verify Started **
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;** Verified OK **
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Info : Listening on port &lt;span style=&#34;color:#f5a97f&#34;&gt;6666&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;for&lt;/span&gt; tcl connections
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Info : Listening on port &lt;span style=&#34;color:#f5a97f&#34;&gt;4444&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;for&lt;/span&gt; telnet connections
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;In a new shell window, launch gdb with elf file specified and pushed into openocd host. OpenOCD and gdb work together to match up what&amp;rsquo;s on the chip with the expected symbol table. The example commands below will show the constant and the loop.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#91d7e3&#34;&gt;cd&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;$YOUR_PROJECT_FOLDER&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;arm-none-eabi-gdb main.elf -iex &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;target extended-remote localhost:3333&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## Optional Layout Changes&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;(&lt;/span&gt;gdb&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;)&lt;/span&gt; layout asm
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;(&lt;/span&gt;gdb&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;)&lt;/span&gt; layout regs  
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## ^x o to switch between&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## ^x a to close&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;(&lt;/span&gt;gdb&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;)&lt;/span&gt; info registers
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;(&lt;/span&gt;gdb&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;)&lt;/span&gt; info register r0
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;(&lt;/span&gt;gdb&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;)&lt;/span&gt; info register r7
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;(&lt;/span&gt;gdb&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;)&lt;/span&gt; info &lt;span style=&#34;color:#91d7e3&#34;&gt;break&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;(&lt;/span&gt;gdb&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;)&lt;/span&gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;break&lt;/span&gt; main_loop
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;(&lt;/span&gt;gdb&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;)&lt;/span&gt; info &lt;span style=&#34;color:#91d7e3&#34;&gt;break&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;(&lt;/span&gt;gdb&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;)&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;continue&lt;/span&gt; &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# ^c to escape&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;(&lt;/span&gt;gdb&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;)&lt;/span&gt; info register r0
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;(&lt;/span&gt;gdb&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;)&lt;/span&gt; info register r7
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;(&lt;/span&gt;gdb&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;)&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;continue&lt;/span&gt; &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# ^c to escape&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;(&lt;/span&gt;gdb&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;)&lt;/span&gt; info register r0
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;(&lt;/span&gt;gdb&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;)&lt;/span&gt; stepi
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;(&lt;/span&gt;gdb&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;)&lt;/span&gt; info register r0
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# etc...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;makefile&#34;&gt;Makefile&lt;/h3&gt;
&lt;p&gt;Based on the AVR Makefile and the commands ran above. Fewer options for now. Critical for this gdb focused example because missing the -g flag makes it kind of useless.&lt;/p&gt;
&lt;p&gt;An important difference&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;MCU = attiny
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;-mmcu=$(MCU)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;MACH = cortex-m0
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;-mcpu=$(MACH)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Different hardware specific version of GCC have different flag sets. Always check!&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://gcc.gnu.org/onlinedocs/gcc/Submodel-Options.html&#34;&gt;https://gcc.gnu.org/onlinedocs/gcc/Submodel-Options.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://gcc.gnu.org/onlinedocs/gcc/AVR-Options.html&#34;&gt;https://gcc.gnu.org/onlinedocs/gcc/AVR-Options.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://gcc.gnu.org/onlinedocs/gcc/ARM-Options.html&#34;&gt;https://gcc.gnu.org/onlinedocs/gcc/ARM-Options.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://community.arm.com/arm-community-blogs/b/tools-software-ides-blog/posts/compiler-flags-across-architectures-march-mtune-and-mcpu&#34;&gt;-march vs -mtune- vs -mcpu for arm&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-make&#34; data-lang=&#34;make&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;###############################################################################
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# Makefile for a simple SAMD21 Assembly project
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;###############################################################################
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## General Flags
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;TARGET&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;?=&lt;/span&gt; hello#set &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; not defined 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;LINKER_FILE&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;?=&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;$(&lt;/span&gt;TARGET&lt;span style=&#34;color:#c6a0f6&#34;&gt;)&lt;/span&gt;.ld
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;MACH&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; cortex-m0
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;TOOL_BASE&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; arm-none-eabi-
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;CC&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;$(&lt;/span&gt;TOOL_BASE&lt;span style=&#34;color:#c6a0f6&#34;&gt;)&lt;/span&gt;gcc
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## Options common to compile, link and assembly rules
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;COMMON&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; -mcpu&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;$(&lt;/span&gt;MACH&lt;span style=&#34;color:#c6a0f6&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;COMMON&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;+=&lt;/span&gt; -mthumb
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## Compile options common for all C compilation units.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;CFLAGS&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;$(&lt;/span&gt;COMMON&lt;span style=&#34;color:#c6a0f6&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;CFLAGS&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;+=&lt;/span&gt; -Wall
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;CFLAGS&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;+=&lt;/span&gt; -g
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;CFLAGS&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;+=&lt;/span&gt; -Os
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## Linker flags
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;LDFLAGS&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;$(&lt;/span&gt;COMMON&lt;span style=&#34;color:#c6a0f6&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;LDFLAGS&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;+=&lt;/span&gt; --specs&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt;nosys.specs -nostdlib -lgcc
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## Objects that must be built in order to link
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;OBJECTS&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;$(&lt;/span&gt;TARGET&lt;span style=&#34;color:#c6a0f6&#34;&gt;)&lt;/span&gt;.o 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## Objects explicitly added by the user
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;LINKONLYOBJECTS&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# Programming support using avrdude. Settings and variables.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;PROGRAMMER&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; openocd
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;PROGRAMMER_FLAGS&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; -f program_and_serve.cfg
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## Build
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;all&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;$(&lt;/span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;TARGET&lt;/span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;)&lt;/span&gt;.elf
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## Compile
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;%.o &lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;:&lt;/span&gt; %.S
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	&lt;span style=&#34;color:#c6a0f6&#34;&gt;$(&lt;/span&gt;CC&lt;span style=&#34;color:#c6a0f6&#34;&gt;)&lt;/span&gt; -x assembler-with-cpp -c &lt;span style=&#34;color:#c6a0f6&#34;&gt;$(&lt;/span&gt;CFLAGS&lt;span style=&#34;color:#c6a0f6&#34;&gt;)&lt;/span&gt; $&amp;lt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;##Link
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;%.elf&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;$(&lt;/span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;OBJECTS&lt;/span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	 &lt;span style=&#34;color:#c6a0f6&#34;&gt;$(&lt;/span&gt;CC&lt;span style=&#34;color:#c6a0f6&#34;&gt;)&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;$(&lt;/span&gt;LDFLAGS&lt;span style=&#34;color:#c6a0f6&#34;&gt;)&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;$(&lt;/span&gt;OBJECTS&lt;span style=&#34;color:#c6a0f6&#34;&gt;)&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;$(&lt;/span&gt;LINKONLYOBJECTS&lt;span style=&#34;color:#c6a0f6&#34;&gt;)&lt;/span&gt;  -T./&lt;span style=&#34;color:#c6a0f6&#34;&gt;$(&lt;/span&gt;LINKER_FILE&lt;span style=&#34;color:#c6a0f6&#34;&gt;)&lt;/span&gt; -o &lt;span style=&#34;color:#c6a0f6&#34;&gt;$(&lt;/span&gt;TARGET&lt;span style=&#34;color:#c6a0f6&#34;&gt;)&lt;/span&gt;.elf
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# Program the device.  
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;program&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;$(&lt;/span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;TARGET&lt;/span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;)&lt;/span&gt;.elf
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	&lt;span style=&#34;color:#c6a0f6&#34;&gt;$(&lt;/span&gt;PROGRAMMER&lt;span style=&#34;color:#c6a0f6&#34;&gt;)&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;$(&lt;/span&gt;PROGRAMMER_FLAGS&lt;span style=&#34;color:#c6a0f6&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## Clean target
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#.PHONY: clean
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;clean&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	-rm -rf &lt;span style=&#34;color:#c6a0f6&#34;&gt;$(&lt;/span&gt;OBJECTS&lt;span style=&#34;color:#c6a0f6&#34;&gt;)&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;$(&lt;/span&gt;TARGET&lt;span style=&#34;color:#c6a0f6&#34;&gt;)&lt;/span&gt;.elf &lt;span style=&#34;color:#c6a0f6&#34;&gt;$(&lt;/span&gt;TARGET&lt;span style=&#34;color:#c6a0f6&#34;&gt;)&lt;/span&gt;.hex &lt;span style=&#34;color:#c6a0f6&#34;&gt;$(&lt;/span&gt;TARGET&lt;span style=&#34;color:#c6a0f6&#34;&gt;)&lt;/span&gt;.lss &lt;span style=&#34;color:#c6a0f6&#34;&gt;$(&lt;/span&gt;TARGET&lt;span style=&#34;color:#c6a0f6&#34;&gt;)&lt;/span&gt;.map 
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;summary&#34;&gt;Summary&lt;/h2&gt;
&lt;p&gt;This assembly example works because there&amp;rsquo;s nothing in it. To do anything else it would be better to have a real start up script for the chip&amp;hellip; a Makefile&amp;hellip; A repo so much to improve! And that&amp;rsquo;s the next post!&lt;/p&gt;
&lt;h2 id=&#34;errata&#34;&gt;Errata&lt;/h2&gt;
&lt;p&gt;I made a mistake when I first posted this (since corrected). So that big table of peripherals is for all SADM21*, not just for the SAMD21E18A [TODO LINK]. I had properly left out the ones that didn&amp;rsquo;t belong in my original original vector table code, but in a fit of insecurity I put them all back in. I&amp;rsquo;ve now taken them out again.  The source of my insecurity was all this code on the internet! When looking at code on github, make sure both projects face the same tradeoffs. Notice the difference between the two files below. One has ALL of peripherals, the other does not. One is called startup_SAMD21.s the other is called startup_samd21e18a.s  The first file supports the whole family at once. Presumably their default handlers can handle it. The second is the one that matches JUST this chip. There is a lot of SADM21.s and SADM21XXX.h code in the world. I was worried I was missing something&amp;hellip; turns out I was. I was missing that it wasn&amp;rsquo;t solving the same problem.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/microsoft/uf2-samdx1/blob/4c900345561949f1c37a367d72eb8e420b01f72f/lib/samd21/samd21a/armcc/Device/SAMD21/Source/ARM/startup_SAMD21.s&#34;&gt;startup_SAMD21.s&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/Microchip-MPLAB-Harmony/dev_packs/blob/345dc12d42a4fdec72117b64a8c3527023bdeca9/Microchip/SAMD21_DFP/3.6.144/samd21a/armcc/armcc/&#34;&gt;startup_samd21e18a.s&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</description>
    </item>
    
    
    
    <item>
      <title>Hello LED on an AVR (ATtiny45) in C</title>
      <link>https://whynotestflight.com/excuses/hello-led-on-an-avr-attiny45-in-c/</link>
      <pubDate>Tue, 02 Apr 2024 00:00:00 +0000</pubDate>
      
      <guid>https://whynotestflight.com/excuses/hello-led-on-an-avr-attiny45-in-c/</guid>
      <description>&lt;p&gt;Related Repo: &lt;a href=&#34;https://github.com/carlynorama/StrippedDownChipRosetta&#34;&gt;https://github.com/carlynorama/StrippedDownChipRosetta&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;I want to start using official &lt;a href=&#34;https://github.com/apple/swift/blob/main/docs/EmbeddedSwift/UserManual.md&#34;&gt;Embedded Swift&lt;/a&gt;, but I was thinking I should have some reference code on some different board families in C handy first.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://en.wikipedia.org/wiki/AVR_microcontrollers&#34;&gt;AVR&lt;/a&gt; (ATtiny this post)&lt;/li&gt;
&lt;li&gt;Probably skip PIC&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://www.microchip.com/en-us/products/microcontrollers-and-microprocessors/32-bit-mcus/sam-32-bit-mcus&#34;&gt;SAM&lt;/a&gt; which are all 32 bit Arm Cortex&lt;/li&gt;
&lt;li&gt;probably straight to &lt;a href=&#34;https://www.st.com/en/microcontrollers-microprocessors/stm32-32-bit-arm-cortex-mcus.html&#34;&gt;STM32&lt;/a&gt; Also 32-bit Arm Cortex MCU&lt;/li&gt;
&lt;li&gt;Maybe &lt;a href=&#34;https://en.wikipedia.org/wiki/ESP32&#34;&gt;ESP32&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Turns out there&amp;rsquo;s a great tutorial series for AVR already done. Mitch Davis has a YouTube playlist:&lt;a href=&#34;https://www.youtube.com/playlist?list=PLNyfXcjhOAwOF-7S-ZoW2wuQ6Y-4hfjMR&#34;&gt;Fundamentals of Microcontrollers - Arduino bare-metal breakdown&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The 9 part video series goes from blinking an LED on an Arduino board to blinking an LED with an ATTiny85 on a breadboard via linkers and optimizers and setting fuses and more.  Assumes basic Arduino knowledge, but no C or other microcontroller experience.  Because this series did such a good job covering what I would have wanted to cover I can just hop on down to where he leaves off by making an example with a switch and a Makefile.&lt;/p&gt;
&lt;p&gt;One note: please unplug your boards when moving around wires.&lt;/p&gt;
&lt;p&gt;More links below for supplemental reference.&lt;/p&gt;
&lt;h3 id=&#34;arduino-101&#34;&gt;Arduino 101&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://docs.arduino.cc/learn/starting-guide/getting-started-arduino/&#34;&gt;https://docs.arduino.cc/learn/starting-guide/getting-started-arduino/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://itp.nyu.edu/physcomp/lessons/&#34;&gt;https://itp.nyu.edu/physcomp/lessons/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;ICs &amp;amp; Micros general info playlist. (General topics. It&amp;rsquo;s old.) &lt;a href=&#34;https://www.youtube.com/watch?v=1qQE5Xwe7fs&amp;amp;list=PLfbQcOtLPyIFqfXwXdpnFJ2EN2RuLUpUl&#34;&gt;https://www.youtube.com/watch?v=1qQE5Xwe7fs&amp;amp;list=PLfbQcOtLPyIFqfXwXdpnFJ2EN2RuLUpUl&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;arduino-on-a-breadboard&#34;&gt;Arduino on a breadboard&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://docs.arduino.cc/built-in-examples/arduino-isp/ArduinoToBreadboard/&#34;&gt;https://docs.arduino.cc/built-in-examples/arduino-isp/ArduinoToBreadboard/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://docs.arduino.cc/retired/hacking/hardware/building-an-arduino-on-a-breadboard/&#34;&gt;https://docs.arduino.cc/retired/hacking/hardware/building-an-arduino-on-a-breadboard/&lt;/a&gt; (back in my day&amp;hellip;)&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;datasheets&#34;&gt;DataSheets&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://ww1.microchip.com/downloads/en/DeviceDoc/Atmel-2586-AVR-8-bit-Microcontroller-ATtiny25-ATtiny45-ATtiny85_Datasheet.pdf&#34;&gt;https://ww1.microchip.com/downloads/en/DeviceDoc/Atmel-2586-AVR-8-bit-Microcontroller-ATtiny25-ATtiny45-ATtiny85_Datasheet.pdf&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;http://ww1.microchip.com/downloads/en/devicedoc/atmel-0856-avr-instruction-set-manual.pdf&#34;&gt;http://ww1.microchip.com/downloads/en/devicedoc/atmel-0856-avr-instruction-set-manual.pdf&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;http://ww1.microchip.com/downloads/en/DeviceDoc/Atmel-7810-Automotive-Microcontrollers-ATmega328P_Datasheet.pdf&#34;&gt;http://ww1.microchip.com/downloads/en/DeviceDoc/Atmel-7810-Automotive-Microcontrollers-ATmega328P_Datasheet.pdf&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;http://ww1.microchip.com/downloads/en/DeviceDoc/ATmega48A-PA-88A-PA-168A-PA-328-P-DS-DS40002061A.pdf&#34;&gt;http://ww1.microchip.com/downloads/en/DeviceDoc/ATmega48A-PA-88A-PA-168A-PA-328-P-DS-DS40002061A.pdf&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;misc-other&#34;&gt;Misc Other&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;http://eleccelerator.com/fusecalc/&#34;&gt;http://eleccelerator.com/fusecalc/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://avrdudes.github.io/avrdude/7.3/avrdude.html&#34;&gt;https://avrdudes.github.io/avrdude/7.3/avrdude.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://www.microchip.com/en-us/application-notes&#34;&gt;https://www.microchip.com/en-us/application-notes&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://www.microchip.com/en-us/products/microcontrollers-and-microprocessors/32-bit-mcus/applications-reference-designs-and-solutions&#34;&gt;https://www.microchip.com/en-us/products/microcontrollers-and-microprocessors/32-bit-mcus/applications-reference-designs-and-solutions&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;a-note-about-the-attiny85-and-doing-things-on-a-breadboard&#34;&gt;A note about the ATtiny85 and doing things on a breadboard.&lt;/h2&gt;
&lt;p&gt;I used to teach in person so I have A LOT of ATtinyX5 dip package chips lying around. Most people these days would buy a dev board (e.g. Arduino Pro mini) that has a surface mount AVR. Probably one that  runs at 3.3V.  I still like the DIP socket boards for prototyping because the DIP chips are sturdier and easily replaceable. I have many products from both companies below.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://www.sparkfun.com/search/results?term=AVR&#34;&gt;SparkFun AVR Search Results&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://learn.adafruit.com/search?q=AVR&#34;&gt;AdaFruit AVR Search Results&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The chip I&amp;rsquo;m actually using is the ATtiny45. It has half the memory of the 85. For the ATTiny the number after the &amp;ldquo;y&amp;rdquo; is the flash memory size in k (it could be &amp;ldquo;16&amp;rdquo;). The last number is an indicator of the number of pins, but but not literally. The &lt;a href=&#34;https://www.microchip.com/en-us/product/ATTINY44&#34;&gt;ATtiny44&lt;/a&gt; has more than the ATtiny45. There&amp;rsquo;s a whole new set of ATTiny&amp;rsquo;s now, too. Here&amp;rsquo;s a guide.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://ww1.microchip.com/downloads/en/DeviceDoc/30010135E.pdf&#34;&gt;AVR® Microcontrollers Peripheral Integration, Quick Reference Guide&lt;/a&gt; (&lt;a href=&#34;https://ww1.microchip.com/downloads/en/DeviceDoc/30010135D.pdf&#34;&gt;previous version&lt;/a&gt; with ATTiny85(V) on it)&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;check-computer-readiness-before-starting&#34;&gt;Check computer readiness before starting&lt;/h2&gt;
&lt;p&gt;All this presumes a machine that has compiled C and Swift, so it may be set up for clang but not avr-gcc.   None of this will use an Arduino IDE&amp;rsquo;s install of these tools so it doesn&amp;rsquo;t matter if that&amp;rsquo;s on the box or not. Nor will any of this require software or libraries from ATMEL (now Microchip). Nor will the code import &lt;a href=&#34;https://github.com/avrdudes/avr-libc&#34;&gt;AVR LibC&lt;/a&gt;.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-zsh&#34; data-lang=&#34;zsh&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;which avr-gcc
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# points to 3rd party repo&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# https://github.com/osx-cross/homebrew-avr&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;brew tap osx-cross/avr 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;brew install avr-gcc
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;brew install avrdude
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## Check install by printing out the compatible mcu&amp;#39;s&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## using zsh not bash escape the ?&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;avrdude -p &lt;span style=&#34;color:#8aadf4&#34;&gt;\?&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;No need for avrdude&amp;rsquo;s -C (config file location) option. My 2024 homebrew install (version 7.3) doesn&amp;rsquo;t seem to need it.&lt;/p&gt;
&lt;h3 id=&#34;confirm-compilation&#34;&gt;Confirm compilation&lt;/h3&gt;
&lt;p&gt;Before I wired up the board, I checked that the code compiled and I got reasonable looking hex/assembly. My hello-world code doesn&amp;rsquo;t duplicate the tutorial exactly, but it&amp;rsquo;s pretty close.&lt;/p&gt;
&lt;p&gt;This code will successfully blink a pin on &lt;em&gt;PB3&lt;/em&gt; (tested.)&lt;/p&gt;
&lt;p&gt;//TODO: (blog meta) chroma treats #define as a comment &lt;a href=&#34;https://github.com/alecthomas/chroma/issues/953&#34;&gt;bug report&lt;/a&gt;&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-C&#34; data-lang=&#34;C&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//blink.c
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//typically handled by AVR LibC
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//10.4.2 PORTB – Port B Data Register
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#define PORTB *((volatile unsigned char*) 0x38) &lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//(0x20 + 0x18)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//10.4.3 DDRB – Port B Data Direction Register
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#define DDRB *((volatile unsigned char*) 0x37)  &lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//(0x20 + 0x17)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#define LED_PIN 3
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//delay for the number of clock cycles
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//approximately micros with default clock
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//(version in AVR LibC)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;void&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;delay&lt;/span&gt;(&lt;span style=&#34;color:#c6a0f6&#34;&gt;volatile&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;long&lt;/span&gt; time) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;while&lt;/span&gt; (time &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;!=&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;0&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        time&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;--&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;int&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;main&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    DDRB &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;|=&lt;/span&gt; (&lt;span style=&#34;color:#f5a97f&#34;&gt;1&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;lt;&amp;lt;&lt;/span&gt;LED_PIN); 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;while&lt;/span&gt; (&lt;span style=&#34;color:#f5a97f&#34;&gt;1&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        PORTB &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;|=&lt;/span&gt; (&lt;span style=&#34;color:#f5a97f&#34;&gt;1&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;lt;&amp;lt;&lt;/span&gt;LED_PIN); &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// pin high
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;        &lt;span style=&#34;color:#8aadf4&#34;&gt;delay&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;50000&lt;/span&gt;); &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//half a second at a 1MHz clock
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;        PORTB &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;amp;=&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;~&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;1&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;lt;&amp;lt;&lt;/span&gt;LED_PIN); &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// pin low
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;        &lt;span style=&#34;color:#8aadf4&#34;&gt;delay&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;50000&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;How to compile, similar to video, with bonus how to get the assembly.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-zsh&#34; data-lang=&#34;zsh&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## (-g turns on debugging information, -Os optimizes)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;avr-gcc -g -Os -mmcu&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt;attiny45 blink.c
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## leads to a.out which can be inspected in a hex editor &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## or save the interleaved disassembly and source with&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;avr-objdump -h -S a.out &amp;gt; dump.txt
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## Make the ihex file for avrdude&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;avr-objcopy -O ihex -j.text -j.data a.out a.hex
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;a href=&#34;blink_dump.txt&#34;&gt;blink_dump.txt&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&#34;wire-up-the-board&#34;&gt;Wire Up the Board&lt;/h2&gt;
&lt;!-- &lt;script type=&#34;module&#34; src=&#34;https://whynotestflight.com/js/kicanvas.js&#34;&gt;&lt;/script&gt;
&lt;script type=&#34;module&#34; src=&#34;https://whynotestflight.com/js/test.js&#34;&gt;&lt;/script&gt;
&lt;kicanvas src=&#34;AttinyBasicBoard.kicad_sch&#34;&gt;&lt;/kicanvas&gt; --&gt;
&lt;p&gt;The videos cover a basic version that will mostly work with the code above (LED inverted and on a different pin). The Arduino on a breadboard links at the top also cover a similar task.&lt;/p&gt;
&lt;p&gt;Here&amp;rsquo;s a photo of my final set up because it&amp;rsquo;s a bit different. Links to a schematic and an annotated BOM.&lt;/p&gt;
&lt;p&gt;Things to note:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;LED Pin is on PB3 not PB1&lt;/li&gt;
&lt;li&gt;for the LED HIGH is OFF (pin output in sink mode, not source mode)&lt;/li&gt;
&lt;li&gt;Input pin uses internal pull up resistor (so none on board), switch closed to GROUND is turning on the LED.&lt;/li&gt;
&lt;li&gt;In the picture you&amp;rsquo;ll see some extra wires &amp;ldquo;to nowhere.&amp;rdquo; I make &amp;ldquo;psuedo headers&amp;rdquo; in my breadboards sometimes so I don&amp;rsquo;t have to keep checking the pin diagrams.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src=&#34;attiny_pins.png&#34; alt=&#34;pin diagram of the ATtiny&#34;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;IMG_1665.jpeg&#34; alt=&#34;Image of the breadboard with the ATtiny, a power circuit, 2 LEDs, two tact switches and a mess of wires.&#34;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;AttinyBasicBoard.png&#34; alt=&#34;Schematic of the breadboard set up&#34;&gt;&lt;/p&gt;
&lt;p&gt;schematic: &lt;a href=&#34;AttinyBasicBoard.kicad_sch&#34;&gt;kicad sch file&lt;/a&gt;&lt;/p&gt;
&lt;h3 id=&#34;bill-of-materials&#34;&gt;Bill of Materials&lt;/h3&gt;
&lt;p&gt;Annotated parts list.&lt;/p&gt;
&lt;table&gt;
  &lt;thead&gt;
      &lt;tr&gt;
          &lt;th style=&#34;text-align: left&#34;&gt;Designator&lt;/th&gt;
          &lt;th style=&#34;text-align: left&#34;&gt;Description&lt;/th&gt;
          &lt;th style=&#34;text-align: left&#34;&gt;Qty&lt;/th&gt;
          &lt;th style=&#34;text-align: left&#34;&gt;Use&lt;/th&gt;
      &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
      &lt;tr&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;SW1, SW2&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;6mm Tact Switch with 5 mm Height&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;2&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;Reset, Digital Input&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;R2, R4*&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;10kΩ axial resistor&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;2&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;external pull up&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;R1, R3†&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;330Ω axial resistor&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;2&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;current limiter&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;J2&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;wires to external power.&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;1&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;external power source (7-16V)&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;J1&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;wires to AVR-ISP programmer&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;1&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;chip programming&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;D2&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;5.0mm LED (Red)&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;1&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;Power Indicator&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;D4&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;5.0mm LED (Yellow)&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;1&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;Digital Output&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;D1**&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;1N4004&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;1&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;protection diode&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;C2&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;10uF polarized electrolytic&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;1&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;input (higher voltage) side&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;C1&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;1uF polarized electrolytic&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;1&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;output (regulated voltage) side&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;U2&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;DIP-8 ATtinyX5&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;1&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;Microcontroller&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;U1&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;LM7805 TO-220 or T-92 fine&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;1&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;Voltage Regulator&lt;/td&gt;
      &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;ul&gt;
&lt;li&gt;* R4 not in picture. Using chip&amp;rsquo;s internal pull up in real circuit, but its important &lt;a href=&#34;https://stackoverflow.com/questions/20512663/assigning-internal-pull-ups-to-input-port&#34;&gt;not to forget to set it&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;† R3 is actually 1k in the picture. Yellow LEDs get bright.&lt;/li&gt;
&lt;li&gt;** D1 not in picture. It&amp;rsquo;s in my power supply.&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://www.electricity-magnetism.org/what-is-the-role-of-a-capacitor-in-a-power-supply-circuit/&#34;&gt;Why caps in the power circuit&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://www.alldatasheet.com/datasheet-pdf/pdf/838007/TI1/LM7805.html&#34;&gt;7805 Datasheet&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;program-the-board&#34;&gt;Program the Board&lt;/h2&gt;
&lt;p&gt;The new code:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-C++&#34; data-lang=&#34;C++&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//10.4.2 PORTB – Port B Data Register
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#define PORTB *((volatile unsigned char*) 0x38) &lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//(0x20 + 0x18)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//10.4.3 DDRB – Port B Data Direction Register
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#define DDRB *((volatile unsigned char*) 0x37)  &lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//(0x20 + 0x17)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//10.4.4 PINB – Port B Input Pins Address
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#define PINB *((volatile unsigned char *)0x36)  &lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//(0x20 + 0x16)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#define LED_PIN 3
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#define SWITCH_PIN 4
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;int&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;main&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//set led pin bit to output
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;    DDRB &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;|=&lt;/span&gt; (&lt;span style=&#34;color:#f5a97f&#34;&gt;1&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;lt;&amp;lt;&lt;/span&gt;LED_PIN);  
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//set switch pin bit to input
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;    DDRB &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;amp;=&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;~&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;1&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;lt;&amp;lt;&lt;/span&gt;SWITCH_PIN); 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;     &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//for voltage high == no press config, sets pull up.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;    PORTB &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;|=&lt;/span&gt; (&lt;span style=&#34;color:#f5a97f&#34;&gt;1&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;lt;&amp;lt;&lt;/span&gt;SWITCH_PIN);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//give the pull up a moment.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//internal pull ups have high R and pin may be slow to reach logic high threshold. If problem, chip has to have settle time out of reset (SUT) or code does. 
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;while&lt;/span&gt; (&lt;span style=&#34;color:#f5a97f&#34;&gt;1&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; (&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;!&lt;/span&gt;(PINB &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;amp;&lt;/span&gt; (&lt;span style=&#34;color:#f5a97f&#34;&gt;1&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;lt;&amp;lt;&lt;/span&gt;SWITCH_PIN))) {  &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//if pressed
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//above if compares (0x000?0000 &amp;amp; 0x00010000) =&amp;gt; 
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// - if true, seeing pull up. button not pressed
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// - if false, seeing ground via closed switch, button pressed
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;            PORTB &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;amp;=&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;~&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;1&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;lt;&amp;lt;&lt;/span&gt;LED_PIN);   &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// pin low, LED ON
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;        } &lt;span style=&#34;color:#c6a0f6&#34;&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            PORTB &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;|=&lt;/span&gt; (&lt;span style=&#34;color:#f5a97f&#34;&gt;1&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;lt;&amp;lt;&lt;/span&gt;LED_PIN);    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// pin high, LED OFF 
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;a href=&#34;switch_control_dump.txt&#34;&gt;switch_control_dump.txt&lt;/a&gt;&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-zsh&#34; data-lang=&#34;zsh&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;avrdude -p t45 -c usbtiny  &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#to confirm board is ready&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## REDO compile with new code, &amp;amp; upload&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;avr-gcc -g -Os -mmcu&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt;attiny45 switch_control.c
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;avr-objcopy -O ihex -j.text -j.data a.out a.hex
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;avrdude -p t45 -c usbtiny -U flash:w:a.hex:i
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;more-on-fuses--clock-settings&#34;&gt;More on Fuses &amp;amp; Clock Settings&lt;/h2&gt;
&lt;p&gt;&lt;a href=&#34;https://www.youtube.com/watch?v=Q2DakPocvfs&amp;amp;list=PLNyfXcjhOAwOF-7S-ZoW2wuQ6Y-4hfjMR&amp;amp;index=5&#34;&gt;Video 5 of the series&lt;/a&gt;(&amp;ldquo;AVRDude and fuses&amp;rdquo;) talks about setting the fuses for the chip&amp;rsquo;s clock settings.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-zsh&#34; data-lang=&#34;zsh&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# memtype:operation:value:format&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# m means direct value, as opposed to i for intel hex&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;avrdude -v -p t45 -c usbtiny -U lfuse:w:0xF2:m
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;I skipped that, but now I want to see the settings for the chip I grabbed.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-zsh&#34; data-lang=&#34;zsh&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# h is hexadecimal mode for the read.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# &amp;#34;each value will get the string 0x prepended.&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;avrdude -v -p t45 -c usbtiny -U hfuse:r:-:h -U lfuse:r:-:h
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;In the output will be:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;avrdude: using SCK period of 10 usec

avrdude: processing -U hfuse:r:-:h
avrdude: reading hfuse memory ...
avrdude: writing output file &amp;lt;stdout&amp;gt;
0xdf 

avrdude: processing -U lfuse:r:-:h
avrdude: reading lfuse memory ...
avrdude: writing output file &amp;lt;stdout&amp;gt;
0x62
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;That means the registers look like:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt; low fuse: 0110 0010
high fuse: 1101 1111
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Both of these values are &lt;a href=&#34;http://eleccelerator.com/fusecalc/fusecalc.php?chip=attiny85&amp;amp;LOW=62&amp;amp;HIGH=DF&amp;amp;EXTENDED=FF&amp;amp;LOCKBIT=FF&#34;&gt;the defaults&lt;/a&gt;, and the clock information is discussed in section 6.2 of the datasheet. ( 1 is unset and 0 is set.)&lt;/p&gt;
&lt;style&gt;
    table.foo {
    width:90%
    margin:0px;
    padding:0px;
    line-height:22px;
    font-size:13px;
    font-family:Arial, Verdana, Tahoma, Helvetica, sans-serif;
    font-weight:200;
    text-decoration:none;
    white-space:pre-wrap;
}
table.foo td {
  width:10%;
  margin: 5px;
}

table.foo th {
    font-family:Arial, Verdana, Tahoma, Helvetica, sans-serif;
    font-weight:200;
}

table.foo strong {
  font-weight:1200;
  
}
&lt;/style&gt;
&lt;table class=&#34;foo&#34;&gt;
  &lt;thead&gt;
      &lt;tr&gt;
          &lt;th style=&#34;text-align: left&#34;&gt;&lt;/th&gt;
          &lt;th style=&#34;text-align: left&#34;&gt;7&lt;/th&gt;
          &lt;th style=&#34;text-align: left&#34;&gt;6&lt;/th&gt;
          &lt;th style=&#34;text-align: left&#34;&gt;5&lt;/th&gt;
          &lt;th style=&#34;text-align: left&#34;&gt;4&lt;/th&gt;
          &lt;th style=&#34;text-align: left&#34;&gt;3&lt;/th&gt;
          &lt;th style=&#34;text-align: left&#34;&gt;2&lt;/th&gt;
          &lt;th style=&#34;text-align: left&#34;&gt;1&lt;/th&gt;
          &lt;th style=&#34;text-align: left&#34;&gt;0&lt;/th&gt;
      &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
      &lt;tr&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;low&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;&lt;strong&gt;CKDIV8&lt;/strong&gt;&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;CKOUT&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;SUT1&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;&lt;strong&gt;SUT0&lt;/strong&gt;&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;&lt;strong&gt;CKSEL3&lt;/strong&gt;&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;&lt;strong&gt;CKSEL2&lt;/strong&gt;&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;CKSEL1&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;&lt;strong&gt;CKSEL0&lt;/strong&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;high&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;RSTDISBL&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;DWEN&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;&lt;strong&gt;SPIEN&lt;/strong&gt;&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;WDTON&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;EESAVE&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;BODLEVEL2&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;BODLEVEL1&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;BODLEVEL0&lt;/td&gt;
      &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;This default setting means the chip is running at 1MHz (8MHz calibrated internal RC oscillator (6.2.3) with the CKDIV8 bit set).&lt;/p&gt;
&lt;p&gt;The 0xF2 setting from the video clears the dividing bit (sets CKDIV8 to 1) and the SUT0 bit as well since it only matters with CKDIV8 is enabled.&lt;/p&gt;
&lt;p&gt;Clock settings matter a lot. Here&amp;rsquo;s some tips.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Why use an external clock? Synchronize with another IC&lt;/li&gt;
&lt;li&gt;Why use a crystal? Higher reliability for real time behavior&lt;/li&gt;
&lt;li&gt;If staying internal, why stick with the 1MHz clock? (or go lower)
&lt;ul&gt;
&lt;li&gt;Lower power&lt;/li&gt;
&lt;li&gt;Easy math (1MHz = once per 0.000001 seconds = every microsecond)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Why not? Something happens faster. Communication protocols, audio, expensive math&amp;hellip;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;My little demo program isn&amp;rsquo;t doing anything fancy so 1MHz works for me.&lt;/p&gt;
&lt;h3 id=&#34;more-info-on-fuses&#34;&gt;More Info on Fuses&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://developerhelp.microchip.com/xwiki/bin/view/products/mcu-mpu/8-bit-avr/structure/fuses/&#34;&gt;https://developerhelp.microchip.com/xwiki/bin/view/products/mcu-mpu/8-bit-avr/structure/fuses/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://www.ladyada.net/learn/avr/fuses.html&#34;&gt;https://www.ladyada.net/learn/avr/fuses.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://embedderslife.wordpress.com/2012/08/20/fuse-bits-arent-that-scary/&#34;&gt;https://embedderslife.wordpress.com/2012/08/20/fuse-bits-arent-that-scary/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;http://eleccelerator.com/fusecalc/fusecalc.php?chip=attiny85&#34;&gt;http://eleccelerator.com/fusecalc/fusecalc.php?chip=attiny85&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;switching-to-a-make-file&#34;&gt;Switching to a Make file&lt;/h2&gt;
&lt;p&gt;Running those compile and upload commands by hand gets old. Enter Makefiles, which I &lt;a href=&#34;https://whynotestflight.com/excuses/so-what-if-i-wanted-to-write-some-c-with-no-swift/&#34;&gt;reviewed before&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;For embedded projects I tend to cheat off of todbot.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/todbot/CtrlM/blob/master/firmware/Makefile&#34;&gt;https://github.com/todbot/CtrlM/blob/master/firmware/Makefile&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/todbot/blink1/blob/main/hardware/firmware/Makefile&#34;&gt;https://github.com/todbot/blink1/blob/main/hardware/firmware/Makefile&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/todbot/FreeM/blob/master/firmware/freem_v1a/Makefile&#34;&gt;https://github.com/todbot/FreeM/blob/master/firmware/freem_v1a/Makefile&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;But here are some demos from AVR LibC&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/avrdudes/avr-libc/blob/main/doc/examples/asmdemo/Makefile&#34;&gt;https://github.com/avrdudes/avr-libc/blob/main/doc/examples/asmdemo/Makefile&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/avrdudes/avr-libc/blob/main/doc/examples/demo/Makefile&#34;&gt;https://github.com/avrdudes/avr-libc/blob/main/doc/examples/demo/Makefile&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/avrdudes/avr-libc/blob/main/doc/examples/stdiodemo/Makefile&#34;&gt;https://github.com/avrdudes/avr-libc/blob/main/doc/examples/stdiodemo/Makefile&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/avrdudes/avr-libc/blob/main/doc/examples/twitest/Makefile&#34;&gt;https://github.com/avrdudes/avr-libc/blob/main/doc/examples/twitest/Makefile&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/avrdudes/avr-libc/blob/main/doc/examples/largedemo/Makefile&#34;&gt;https://github.com/avrdudes/avr-libc/blob/main/doc/examples/largedemo/Makefile&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Today I&amp;rsquo;ll roll one to better match the commands already shown.&lt;/p&gt;
&lt;p&gt;Some differences?&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;uses the &lt;a href=&#34;https://en.wikipedia.org/wiki/Executable_and_Linkable_Format&#34;&gt;elf file format&lt;/a&gt; instead of the .out for the intermediary&lt;/li&gt;
&lt;li&gt;uses the target name rather than &amp;ldquo;a&amp;rdquo;&lt;/li&gt;
&lt;li&gt;makes a lss (listing file, I called it dump.txt earlier) file&lt;/li&gt;
&lt;li&gt;makes a map file (debugging map)&lt;/li&gt;
&lt;li&gt;can switch which target with &lt;code&gt;make TARGET=switch_control&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;can compile and run in one step with  which target with &lt;code&gt;make TARGET=switch_control program&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;I left out everything about the fuses for now, but there is an erase function.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I tend to have the Makefile to put build products in a separate folder, but since I&amp;rsquo;m undecided on how I&amp;rsquo;m going to organize these demo files I&amp;rsquo;m skipping that for now.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-makefile&#34; data-lang=&#34;makefile&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;###############################################################################
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# Makefile for a simple ATtiny project
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;###############################################################################
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## General Flags
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;TARGET&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;?=&lt;/span&gt; blink &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#set if not defined &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;MCU&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; attiny45
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# for when using AVR LibC
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#F_CPU = 16000000   # 16MHz on Arduino board
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#F_CPU = 8000000    # internal osc
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#F_CPU = 1000000    # internal osc w/ clkdiv8
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#F_CPU  =  500000   # internal osc w/ clkdiv16
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#F_CPU =  250000    # internal osc w/ clkdiv32
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# Theses values are currently the defaults. 
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;LFUSE&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt;0x62
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;HFUSE&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt;0xDF
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;EFUSE&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt;0xFF
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;CC&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; avr-gcc
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;CPP&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; avr-g++
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## Options common to compile, link and assembly rules
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;COMMON&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; -mmcu&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;$(&lt;/span&gt;MCU&lt;span style=&#34;color:#c6a0f6&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## Compile options common for all C compilation units.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;CFLAGS&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;$(&lt;/span&gt;COMMON&lt;span style=&#34;color:#c6a0f6&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;CFLAGS&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;+=&lt;/span&gt; -Wall
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;CFLAGS&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;+=&lt;/span&gt; -g
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;CFLAGS&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;+=&lt;/span&gt; -Os
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# for when using AVR LibC // i.e. #if F_CPU == 500000 type code
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#Flags that start with -D are a define 
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#equivalent to #define F_CPU = the variable value
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#CFLAGS += -DF_CPU=$(F_CPU) #creates the F_CPU var for the compiler. 
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## Linker flags
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;LDFLAGS&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;$(&lt;/span&gt;COMMON&lt;span style=&#34;color:#c6a0f6&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;LDFLAGS&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;+=&lt;/span&gt;  -Wl,-Map&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;$(&lt;/span&gt;TARGET&lt;span style=&#34;color:#c6a0f6&#34;&gt;)&lt;/span&gt;.map
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## Objects that must be built in order to link
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;OBJECTS&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;$(&lt;/span&gt;TARGET&lt;span style=&#34;color:#c6a0f6&#34;&gt;)&lt;/span&gt;.o 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## Intel Hex file production flags
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;HEX_FLASH_FLAGS&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; -j.text -j.data 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## Objects explicitly added by the user
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;LINKONLYOBJECTS&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# Programming support using avrdude. Settings and variables.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;AVRDUDE&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; avrdude
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;AVRDUDE_PROGRAMMER&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; usbtiny
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#AVRDUDE_PRODUCT = t45
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;AVRDUDE_WRITE_FLASH&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; -U flash:w:&lt;span style=&#34;color:#c6a0f6&#34;&gt;$(&lt;/span&gt;TARGET&lt;span style=&#34;color:#c6a0f6&#34;&gt;)&lt;/span&gt;.hex:i
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;AVRDUDE_FLAGS&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; -p &lt;span style=&#34;color:#c6a0f6&#34;&gt;$(&lt;/span&gt;MCU&lt;span style=&#34;color:#c6a0f6&#34;&gt;)&lt;/span&gt; -c &lt;span style=&#34;color:#c6a0f6&#34;&gt;$(&lt;/span&gt;AVRDUDE_PROGRAMMER&lt;span style=&#34;color:#c6a0f6&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## Build
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;all&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;$(&lt;/span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;TARGET&lt;/span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;)&lt;/span&gt;.elf &lt;span style=&#34;color:#c6a0f6&#34;&gt;$(&lt;/span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;TARGET&lt;/span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;)&lt;/span&gt;.hex &lt;span style=&#34;color:#c6a0f6&#34;&gt;$(&lt;/span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;TARGET&lt;/span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;)&lt;/span&gt;.lss size
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## Compile
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;%.o &lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;:&lt;/span&gt; %.c
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	&lt;span style=&#34;color:#c6a0f6&#34;&gt;$(&lt;/span&gt;CC&lt;span style=&#34;color:#c6a0f6&#34;&gt;)&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;$(&lt;/span&gt;INCLUDES&lt;span style=&#34;color:#c6a0f6&#34;&gt;)&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;$(&lt;/span&gt;CFLAGS&lt;span style=&#34;color:#c6a0f6&#34;&gt;)&lt;/span&gt; -c  $&amp;lt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;##Link
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;%.elf&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;$(&lt;/span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;OBJECTS&lt;/span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	 &lt;span style=&#34;color:#c6a0f6&#34;&gt;$(&lt;/span&gt;CC&lt;span style=&#34;color:#c6a0f6&#34;&gt;)&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;$(&lt;/span&gt;LDFLAGS&lt;span style=&#34;color:#c6a0f6&#34;&gt;)&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;$(&lt;/span&gt;OBJECTS&lt;span style=&#34;color:#c6a0f6&#34;&gt;)&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;$(&lt;/span&gt;LINKONLYOBJECTS&lt;span style=&#34;color:#c6a0f6&#34;&gt;)&lt;/span&gt; -o &lt;span style=&#34;color:#c6a0f6&#34;&gt;$(&lt;/span&gt;TARGET&lt;span style=&#34;color:#c6a0f6&#34;&gt;)&lt;/span&gt;.elf
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;%.hex&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;$(&lt;/span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;TARGET&lt;/span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;)&lt;/span&gt;.elf
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	avr-objcopy -O ihex &lt;span style=&#34;color:#c6a0f6&#34;&gt;$(&lt;/span&gt;HEX_FLASH_FLAGS&lt;span style=&#34;color:#c6a0f6&#34;&gt;)&lt;/span&gt;  $&amp;lt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;$@&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;%.lss&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;$(&lt;/span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;TARGET&lt;/span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;)&lt;/span&gt;.elf
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	avr-objdump -h -S $&amp;lt; &amp;gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;$@&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;size&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;:&lt;/span&gt; ${TARGET}.elf
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	@echo
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	@avr-size -C --mcu&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;${&lt;/span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;MCU&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;}&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;${&lt;/span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;TARGET&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;}&lt;/span&gt;.elf
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;erase&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	&lt;span style=&#34;color:#c6a0f6&#34;&gt;$(&lt;/span&gt;AVRDUDE&lt;span style=&#34;color:#c6a0f6&#34;&gt;)&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;$(&lt;/span&gt;AVRDUDE_FLAGS&lt;span style=&#34;color:#c6a0f6&#34;&gt;)&lt;/span&gt; -e -U lfuse:w:&lt;span style=&#34;color:#c6a0f6&#34;&gt;$(&lt;/span&gt;LFUSE&lt;span style=&#34;color:#c6a0f6&#34;&gt;)&lt;/span&gt;:m -U hfuse:w:&lt;span style=&#34;color:#c6a0f6&#34;&gt;$(&lt;/span&gt;HFUSE&lt;span style=&#34;color:#c6a0f6&#34;&gt;)&lt;/span&gt;:m -U efuse:w:&lt;span style=&#34;color:#c6a0f6&#34;&gt;$(&lt;/span&gt;EFUSE&lt;span style=&#34;color:#c6a0f6&#34;&gt;)&lt;/span&gt;:m
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# Program the device.  
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;program&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;$(&lt;/span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;TARGET&lt;/span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;)&lt;/span&gt;.hex
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	&lt;span style=&#34;color:#c6a0f6&#34;&gt;$(&lt;/span&gt;AVRDUDE&lt;span style=&#34;color:#c6a0f6&#34;&gt;)&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;$(&lt;/span&gt;AVRDUDE_FLAGS&lt;span style=&#34;color:#c6a0f6&#34;&gt;)&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;$(&lt;/span&gt;AVRDUDE_WRITE_FLASH&lt;span style=&#34;color:#c6a0f6&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## Clean target
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#.PHONY: clean
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;clean&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	-rm -rf &lt;span style=&#34;color:#c6a0f6&#34;&gt;$(&lt;/span&gt;OBJECTS&lt;span style=&#34;color:#c6a0f6&#34;&gt;)&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;$(&lt;/span&gt;TARGET&lt;span style=&#34;color:#c6a0f6&#34;&gt;)&lt;/span&gt;.elf &lt;span style=&#34;color:#c6a0f6&#34;&gt;$(&lt;/span&gt;TARGET&lt;span style=&#34;color:#c6a0f6&#34;&gt;)&lt;/span&gt;.hex &lt;span style=&#34;color:#c6a0f6&#34;&gt;$(&lt;/span&gt;TARGET&lt;span style=&#34;color:#c6a0f6&#34;&gt;)&lt;/span&gt;.lss &lt;span style=&#34;color:#c6a0f6&#34;&gt;$(&lt;/span&gt;TARGET&lt;span style=&#34;color:#c6a0f6&#34;&gt;)&lt;/span&gt;.map 
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The Swift/clang ecosystem prefers CMake, which I don&amp;rsquo;t know very well at all (&lt;a href=&#34;https://whynotestflight.com/excuses/cmake-overview/&#34;&gt;CMake hello world post&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;I guess I&amp;rsquo;ll be learning!&lt;/p&gt;
</description>
    </item>
    
    
    
    <item>
      <title>What would be a very simple working Decoder?</title>
      <link>https://whynotestflight.com/excuses/what-would-be-a-very-simple-working-decoder/</link>
      <pubDate>Sun, 31 Mar 2024 00:00:00 +0000</pubDate>
      
      <guid>https://whynotestflight.com/excuses/what-would-be-a-very-simple-working-decoder/</guid>
      <description>&lt;p&gt;After finding a couple of great public examples of simple Encoders (&lt;a href=&#34;https://talk.objc.io/episodes/S01E348-routing-with-codable-encoding&#34;&gt;swift talk&lt;/a&gt; | &lt;a href=&#34;https://stackoverflow.com/questions/45169254/&#34;&gt;stack overflow&lt;/a&gt;), I did not find the same for a Decoder. Here&amp;rsquo;s my shot at it.  Like the very good but behind a paywall &lt;a href=&#34;https://talk.objc.io/episodes/S01E349-routing-with-codable-decoding&#34;&gt;swift talk&lt;/a&gt; example, it has limited use. Both were designed with a single type in mind. This one can decode a single serialized struct with Strings, Ints and Dates as properties.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;property delimited by &amp;ldquo;/&amp;rdquo;&lt;/li&gt;
&lt;li&gt;key-value delimited by &amp;ldquo;:&amp;rdquo;&lt;/li&gt;
&lt;li&gt;lenient about whitespace.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The SimpleCoder Decoder will need a much more complicated parser and will handle more types.&lt;/p&gt;
&lt;p&gt;So with a post about &lt;a href=&#34;https://whynotestflight.com/excuses/wait-how-do-i-scan-text-again/&#34;&gt;string munching&lt;/a&gt; and one about &lt;a href=&#34;:/excuses/date-parsing.-nose-wrinkle./&#34;&gt;date parsing&lt;/a&gt; in the rear-view let&amp;rsquo;s make a Decoder!&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;houseplant_decoder.txt&#34;&gt;Finished playground code&lt;/a&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;input checked=&#34;&#34; disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; remember how to inspect strings in general&lt;/li&gt;
&lt;li&gt;&lt;input checked=&#34;&#34; disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; decide about Dates specifically&lt;/li&gt;
&lt;li&gt;&lt;input disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; write a really really simple decoder to walk through the process &amp;lt;=&lt;/li&gt;
&lt;li&gt;&lt;input disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; inspect other peoples decoders&lt;/li&gt;
&lt;li&gt;&lt;input disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; write the string -&amp;gt; tree step for SimpleCoder&lt;/li&gt;
&lt;li&gt;&lt;input disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; finish the full decoder (with round trip tests)&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;using-the-decoder&#34;&gt;Using the Decoder&lt;/h2&gt;
&lt;p&gt;First updating the struct to actually use &lt;code&gt;Date&lt;/code&gt; in the struct and add an &lt;code&gt;Int&lt;/code&gt; for good measure.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;HousePlant&lt;/span&gt;:Codable {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;commonName&lt;/span&gt;:&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;whereAcquired&lt;/span&gt;:&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;?
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;dateAcquired&lt;/span&gt;:Date
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//NOTE THE VAR. `let` with a default wil not be decoded.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;currentPropCount&lt;/span&gt;:&lt;span style=&#34;color:#91d7e3&#34;&gt;Int&lt;/span&gt; = &lt;span style=&#34;color:#f5a97f&#34;&gt;0&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;dateOfDeath&lt;/span&gt;:Date?
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Thanks to some handy code completions in XCode we can peak at the synthesized Codable conformance:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;enum&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;CodingKeys&lt;/span&gt;: CodingKey {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;case&lt;/span&gt; commonName
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;case&lt;/span&gt; whereAcquired
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;case&lt;/span&gt; dateAcquired
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;case&lt;/span&gt; currentPropCount
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;case&lt;/span&gt; dateOfDeath
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;init&lt;/span&gt;(from decoder: any Decoder) &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;container&lt;/span&gt; = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; decoder.container(keyedBy: CodingKeys.&lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;.commonName = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; container.decode(&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;.&lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;, forKey: .commonName)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;.whereAcquired = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; container.decodeIfPresent(&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;.&lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;, forKey: .whereAcquired)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;.dateAcquired = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; container.decode(Date.&lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;, forKey: .dateAcquired)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;.currentPropCount = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; container.decodeIfPresent(&lt;span style=&#34;color:#91d7e3&#34;&gt;Int&lt;/span&gt;.&lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;, forKey: .currentPropCount)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;.dateOfDeath = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; container.decodeIfPresent(Date.&lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;, forKey: .dateOfDeath)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;encode&lt;/span&gt;(to encoder: any Encoder) &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;container&lt;/span&gt; = encoder.container(keyedBy: CodingKeys.&lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; container.encode(&lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;.commonName, forKey: .commonName)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; container.encodeIfPresent(&lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;.whereAcquired, forKey: .whereAcquired)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; container.encode(&lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;.dateAcquired, forKey: .dateAcquired)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; container.encode(&lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;.currentPropCount, forKey: .currentPropCount)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; container.encodeIfPresent(&lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;.dateOfDeath, forKey: .dateOfDeath)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;From the &lt;code&gt;init(from decoder: any Decoder)&lt;/code&gt; one can tell that the Decoder needs to be able to produce values when given a CodingKey and a Type.&lt;/p&gt;
&lt;p&gt;Using that init would look like:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//Have raw input&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;serializedHousePlant&lt;/span&gt; = &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;commonName:spider plant/whereAcquired:Trader Joe&amp;#39;s/dateAcquired: 2024-03-12T16:12:07Z / currentPropCount:8 &amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//have a decoder that has a chance of doing the lexical analysis&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;decoder&lt;/span&gt; = HousePlantDecoder(serializedHousePlant)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//Codable finishes &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;myHousePlant&lt;/span&gt; = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; HousePlant(from: decoder)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Our decoder holds a potential HousePlant in its belly or BUST.&lt;/p&gt;
&lt;h2 id=&#34;the-data-type&#34;&gt;The Data Type&lt;/h2&gt;
&lt;p&gt;Using the same reference-box as SimpleCoder&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;final&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;SimpleCoderData&lt;/span&gt;&amp;lt;Value&amp;gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;storage&lt;/span&gt;:Value
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;init&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; value: Value) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;.storage = value
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;declare-and-conform&#34;&gt;Declare and conform&lt;/h2&gt;
&lt;p&gt;Notice the fatalError on the SingleValueContainer and UnkeyedContainer? Well, a single serialized HousePlant will never need them.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;HousePlantDecoder&lt;/span&gt;:Decoder {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;data&lt;/span&gt;:SimpleCoderData&amp;lt;&lt;span style=&#34;color:#91d7e3&#34;&gt;Dictionary&lt;/span&gt;&amp;lt;&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;,&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;&amp;gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;codingPath&lt;/span&gt;: [any CodingKey] = []
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;userInfo&lt;/span&gt;: [CodingUserInfoKey : &lt;span style=&#34;color:#91d7e3&#34;&gt;Any&lt;/span&gt;] = [:]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;container&lt;/span&gt;&amp;lt;Key&amp;gt;(keyedBy type: Key.&lt;span style=&#34;color:#c6a0f6&#34;&gt;Type&lt;/span&gt;) &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; -&amp;gt; KeyedDecodingContainer&amp;lt;Key&amp;gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;where&lt;/span&gt; Key : CodingKey {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        KeyedDecodingContainer(HousePlantDecoderKDC(decoder: &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;unkeyedContainer&lt;/span&gt;() &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; -&amp;gt; any UnkeyedDecodingContainer {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#91d7e3&#34;&gt;fatalError&lt;/span&gt;()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;singleValueContainer&lt;/span&gt;() &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; -&amp;gt; any SingleValueDecodingContainer {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#91d7e3&#34;&gt;fatalError&lt;/span&gt;()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;parsing-initializer&#34;&gt;Parsing initializer&lt;/h2&gt;
&lt;p&gt;Can a Dictionary&amp;lt;String,String&amp;gt; even happen? If not, I don&amp;rsquo;t even want to bother making the Decoder.&lt;/p&gt;
&lt;p&gt;The &lt;a href=&#34;https://whynotestflight.com/excuses/wait-how-do-i-scan-text-again/#move-the-index&#34;&gt;second parser from the string scanning post&lt;/a&gt; nicely balances speed and complexity.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;extension&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;HousePlantDecoder&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;parse&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; inputString:&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;) &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; -&amp;gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;Dictionary&lt;/span&gt;&amp;lt;&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;,&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;&amp;gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;fullKeyValueList&lt;/span&gt; = inputString.&lt;span style=&#34;color:#91d7e3&#34;&gt;split&lt;/span&gt;(separator: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;/&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;result&lt;/span&gt;:&lt;span style=&#34;color:#91d7e3&#34;&gt;Dictionary&lt;/span&gt;&amp;lt;&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;,&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;&amp;gt; = [:]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; fullKeyValueList.&lt;span style=&#34;color:#91d7e3&#34;&gt;reduce&lt;/span&gt;(into: result){ result, item &lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;firstColonIndex&lt;/span&gt; = item.firstIndex(of: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;:&amp;#34;&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;key&lt;/span&gt; = item
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    .&lt;span style=&#34;color:#c6a0f6&#34;&gt;prefix&lt;/span&gt;(upTo: firstColonIndex)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    .trimmingCharacters(&lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt;: .whitespacesAndNewlines)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;value&lt;/span&gt; = item
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    .&lt;span style=&#34;color:#91d7e3&#34;&gt;suffix&lt;/span&gt;(from: item.index(firstColonIndex, offsetBy: &lt;span style=&#34;color:#f5a97f&#34;&gt;1&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    .trimmingCharacters(&lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt;: .whitespacesAndNewlines)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                result[&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;(key)] = &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;(value)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            } &lt;span style=&#34;color:#c6a0f6&#34;&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#c6a0f6&#34;&gt;throw&lt;/span&gt; HousePlantError.notAKeyValuePair
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;init&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; inputString:&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;) &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;.data = SimpleCoderData(&lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; HousePlantDecoder.parse(inputString))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;custom-functions-for-containers&#34;&gt;Custom Functions for Containers&lt;/h2&gt;
&lt;p&gt;The containers will need to retrieve values from the storage, and throw errors if the values aren&amp;rsquo;t there.&lt;/p&gt;
&lt;p&gt;Also, the date decoder from the &lt;a href=&#34;:/excuses/date-parsing.-nose-wrinkle./&#34;&gt;previous post&lt;/a&gt; should go in there since our date isn&amp;rsquo;t in timeIntervalSinceReferenceDate format (&lt;a href=&#34;https://whynotestflight.com/excuses/and-what-can-i-make-a-custom-encoder-do/#fixing-the-dates&#34;&gt;the default&lt;/a&gt;).&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;extension&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;HousePlantDecoder&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;retrieveValue&lt;/span&gt;(forKey codingKey:CodingKey) &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; -&amp;gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;guard&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;value&lt;/span&gt; = data.storage[codingKey.stringValue] &lt;span style=&#34;color:#c6a0f6&#34;&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;throw&lt;/span&gt; DecodingError.keyNotFound(codingKey, DecodingError.Context(codingPath: codingPath, debugDescription: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Didn&amp;#39;t find key in decoder data.&amp;#34;&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; value
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;_decodeDate&lt;/span&gt;(from value:&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;) &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; -&amp;gt; Date {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;format&lt;/span&gt; = &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; value.&lt;span style=&#34;color:#91d7e3&#34;&gt;contains&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;:&amp;#34;&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                        Date.ISO8601FormatStyle.iso8601
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    } &lt;span style=&#34;color:#c6a0f6&#34;&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                        Date.ISO8601FormatStyle.iso8601
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                            .year().month().day()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;guard&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;date&lt;/span&gt; = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt;? format.parse(value) &lt;span style=&#34;color:#c6a0f6&#34;&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;throw&lt;/span&gt; DecodingError.dataCorrupted(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                .&lt;span style=&#34;color:#ed8796&#34;&gt;init&lt;/span&gt;(codingPath: [], debugDescription: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;String not in expected &lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;format.parseStrategy&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt; format.&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            )
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; date
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;keyeddecodingcontainerprotocol&#34;&gt;KeyedDecodingContainerProtocol&lt;/h2&gt;
&lt;p&gt;Almost the bare minimum to get it working.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;HousePlantDecoderKDC&lt;/span&gt;&amp;lt;Key:CodingKey&amp;gt;:KeyedDecodingContainerProtocol {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;decoder&lt;/span&gt;:HousePlantDecoder
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;codingPath&lt;/span&gt;: [any CodingKey] { decoder.codingPath }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;allKeys&lt;/span&gt;: [Key] {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        decoder.data.storage.keys.compactMap({ Key(stringValue: &lt;span style=&#34;color:#f4dbd6&#34;&gt;$0&lt;/span&gt;) })
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;contains&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; key: Key) -&amp;gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;Bool&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        decoder.data.storage.keys.&lt;span style=&#34;color:#91d7e3&#34;&gt;contains&lt;/span&gt;(key.stringValue)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;decodeNil&lt;/span&gt;(forKey key: Key) &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; -&amp;gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;Bool&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//return true if the value should be .none&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//false if .some, and an attempt should be made to decode the&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//wrapped value&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; decoder.data.storage.keys.&lt;span style=&#34;color:#91d7e3&#34;&gt;contains&lt;/span&gt;(key.stringValue) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;value&lt;/span&gt; = decoder.data.storage[key.stringValue]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; value == &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;NULL&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;||&lt;/span&gt; value == &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;nil&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        } &lt;span style=&#34;color:#c6a0f6&#34;&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;decode&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; type: &lt;span style=&#34;color:#91d7e3&#34;&gt;Bool&lt;/span&gt;.&lt;span style=&#34;color:#c6a0f6&#34;&gt;Type&lt;/span&gt;, forKey key: Key) &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; -&amp;gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;Bool&lt;/span&gt; { &lt;span style=&#34;color:#91d7e3&#34;&gt;fatalError&lt;/span&gt;() }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;decode&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; type: &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;.&lt;span style=&#34;color:#c6a0f6&#34;&gt;Type&lt;/span&gt;, forKey key: Key) &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; -&amp;gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; decoder.retrieveValue(forKey: key)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;decode&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; type: &lt;span style=&#34;color:#91d7e3&#34;&gt;Double&lt;/span&gt;.&lt;span style=&#34;color:#c6a0f6&#34;&gt;Type&lt;/span&gt;, forKey key: Key) &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; -&amp;gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;Double&lt;/span&gt; { &lt;span style=&#34;color:#91d7e3&#34;&gt;fatalError&lt;/span&gt;() }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;decode&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; type: &lt;span style=&#34;color:#91d7e3&#34;&gt;Float&lt;/span&gt;.&lt;span style=&#34;color:#c6a0f6&#34;&gt;Type&lt;/span&gt;, forKey key: Key) &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; -&amp;gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;Float&lt;/span&gt; { &lt;span style=&#34;color:#91d7e3&#34;&gt;fatalError&lt;/span&gt;() }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;decode&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; type: &lt;span style=&#34;color:#91d7e3&#34;&gt;Int&lt;/span&gt;.&lt;span style=&#34;color:#c6a0f6&#34;&gt;Type&lt;/span&gt;, forKey key: Key) &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; -&amp;gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;Int&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;value&lt;/span&gt; = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; decoder.retrieveValue(forKey: key)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;int&lt;/span&gt; = &lt;span style=&#34;color:#91d7e3&#34;&gt;Int&lt;/span&gt;(value) { &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; int }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;throw&lt;/span&gt; DecodingError.typeMismatch(type, DecodingError.Context(codingPath: codingPath, debugDescription: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Could not make &lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;type&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt; from &lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;value&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;decode&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; type: &lt;span style=&#34;color:#91d7e3&#34;&gt;Int8&lt;/span&gt;.&lt;span style=&#34;color:#c6a0f6&#34;&gt;Type&lt;/span&gt;, forKey key: Key) &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; -&amp;gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;Int8&lt;/span&gt; { &lt;span style=&#34;color:#91d7e3&#34;&gt;fatalError&lt;/span&gt;() }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;decode&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; type: &lt;span style=&#34;color:#91d7e3&#34;&gt;Int16&lt;/span&gt;.&lt;span style=&#34;color:#c6a0f6&#34;&gt;Type&lt;/span&gt;, forKey key: Key) &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; -&amp;gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;Int16&lt;/span&gt; { &lt;span style=&#34;color:#91d7e3&#34;&gt;fatalError&lt;/span&gt;() }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;decode&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; type: &lt;span style=&#34;color:#91d7e3&#34;&gt;Int32&lt;/span&gt;.&lt;span style=&#34;color:#c6a0f6&#34;&gt;Type&lt;/span&gt;, forKey key: Key) &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; -&amp;gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;Int32&lt;/span&gt; { &lt;span style=&#34;color:#91d7e3&#34;&gt;fatalError&lt;/span&gt;() }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;decode&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; type: &lt;span style=&#34;color:#91d7e3&#34;&gt;Int64&lt;/span&gt;.&lt;span style=&#34;color:#c6a0f6&#34;&gt;Type&lt;/span&gt;, forKey key: Key) &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; -&amp;gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;Int64&lt;/span&gt; { &lt;span style=&#34;color:#91d7e3&#34;&gt;fatalError&lt;/span&gt;() }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;decode&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; type: &lt;span style=&#34;color:#91d7e3&#34;&gt;UInt&lt;/span&gt;.&lt;span style=&#34;color:#c6a0f6&#34;&gt;Type&lt;/span&gt;, forKey key: Key) &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; -&amp;gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;UInt&lt;/span&gt; { &lt;span style=&#34;color:#91d7e3&#34;&gt;fatalError&lt;/span&gt;() }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;decode&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; type: &lt;span style=&#34;color:#91d7e3&#34;&gt;UInt8&lt;/span&gt;.&lt;span style=&#34;color:#c6a0f6&#34;&gt;Type&lt;/span&gt;, forKey key: Key) &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; -&amp;gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;UInt8&lt;/span&gt; { &lt;span style=&#34;color:#91d7e3&#34;&gt;fatalError&lt;/span&gt;() }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;decode&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; type: &lt;span style=&#34;color:#91d7e3&#34;&gt;UInt16&lt;/span&gt;.&lt;span style=&#34;color:#c6a0f6&#34;&gt;Type&lt;/span&gt;, forKey key: Key) &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; -&amp;gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;UInt16&lt;/span&gt; { &lt;span style=&#34;color:#91d7e3&#34;&gt;fatalError&lt;/span&gt;() }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;decode&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; type: &lt;span style=&#34;color:#91d7e3&#34;&gt;UInt32&lt;/span&gt;.&lt;span style=&#34;color:#c6a0f6&#34;&gt;Type&lt;/span&gt;, forKey key: Key) &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; -&amp;gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;UInt32&lt;/span&gt; { &lt;span style=&#34;color:#91d7e3&#34;&gt;fatalError&lt;/span&gt;() }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;decode&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; type: &lt;span style=&#34;color:#91d7e3&#34;&gt;UInt64&lt;/span&gt;.&lt;span style=&#34;color:#c6a0f6&#34;&gt;Type&lt;/span&gt;, forKey key: Key) &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; -&amp;gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;UInt64&lt;/span&gt; { &lt;span style=&#34;color:#91d7e3&#34;&gt;fatalError&lt;/span&gt;() }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;decode&lt;/span&gt;&amp;lt;T&amp;gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; type: T.&lt;span style=&#34;color:#c6a0f6&#34;&gt;Type&lt;/span&gt;, forKey key: Key) &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; -&amp;gt; T &lt;span style=&#34;color:#c6a0f6&#34;&gt;where&lt;/span&gt; T : Decodable {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;switch&lt;/span&gt; type {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;case&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;is&lt;/span&gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;Bool&lt;/span&gt;.&lt;span style=&#34;color:#c6a0f6&#34;&gt;Type&lt;/span&gt;: &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; decode(&lt;span style=&#34;color:#91d7e3&#34;&gt;Bool&lt;/span&gt;.&lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;, forKey: key) &lt;span style=&#34;color:#c6a0f6&#34;&gt;as&lt;/span&gt;! T
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;case&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;is&lt;/span&gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;.&lt;span style=&#34;color:#c6a0f6&#34;&gt;Type&lt;/span&gt;: &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; decode(&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;.&lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;, forKey: key) &lt;span style=&#34;color:#c6a0f6&#34;&gt;as&lt;/span&gt;! T
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;case&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;is&lt;/span&gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;Double&lt;/span&gt;.&lt;span style=&#34;color:#c6a0f6&#34;&gt;Type&lt;/span&gt;: &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; decode(&lt;span style=&#34;color:#91d7e3&#34;&gt;Double&lt;/span&gt;.&lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;, forKey: key) &lt;span style=&#34;color:#c6a0f6&#34;&gt;as&lt;/span&gt;! T
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;case&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;is&lt;/span&gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;Float&lt;/span&gt;.&lt;span style=&#34;color:#c6a0f6&#34;&gt;Type&lt;/span&gt;: &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; decode(&lt;span style=&#34;color:#91d7e3&#34;&gt;Float&lt;/span&gt;.&lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;, forKey: key) &lt;span style=&#34;color:#c6a0f6&#34;&gt;as&lt;/span&gt;! T
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;case&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;is&lt;/span&gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;Int&lt;/span&gt;.&lt;span style=&#34;color:#c6a0f6&#34;&gt;Type&lt;/span&gt;: &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; decode(&lt;span style=&#34;color:#91d7e3&#34;&gt;Int&lt;/span&gt;.&lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;, forKey: key) &lt;span style=&#34;color:#c6a0f6&#34;&gt;as&lt;/span&gt;! T
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;case&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;is&lt;/span&gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;Int8&lt;/span&gt;.&lt;span style=&#34;color:#c6a0f6&#34;&gt;Type&lt;/span&gt;: &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; decode(&lt;span style=&#34;color:#91d7e3&#34;&gt;Int8&lt;/span&gt;.&lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;, forKey: key) &lt;span style=&#34;color:#c6a0f6&#34;&gt;as&lt;/span&gt;! T
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;case&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;is&lt;/span&gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;Int16&lt;/span&gt;.&lt;span style=&#34;color:#c6a0f6&#34;&gt;Type&lt;/span&gt;: &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; decode(&lt;span style=&#34;color:#91d7e3&#34;&gt;Int16&lt;/span&gt;.&lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;, forKey: key) &lt;span style=&#34;color:#c6a0f6&#34;&gt;as&lt;/span&gt;! T
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;case&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;is&lt;/span&gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;Int32&lt;/span&gt;.&lt;span style=&#34;color:#c6a0f6&#34;&gt;Type&lt;/span&gt;: &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; decode(&lt;span style=&#34;color:#91d7e3&#34;&gt;Int32&lt;/span&gt;.&lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;, forKey: key) &lt;span style=&#34;color:#c6a0f6&#34;&gt;as&lt;/span&gt;! T
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;case&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;is&lt;/span&gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;Int64&lt;/span&gt;.&lt;span style=&#34;color:#c6a0f6&#34;&gt;Type&lt;/span&gt;: &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; decode(&lt;span style=&#34;color:#91d7e3&#34;&gt;Int64&lt;/span&gt;.&lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;, forKey: key) &lt;span style=&#34;color:#c6a0f6&#34;&gt;as&lt;/span&gt;! T
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;case&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;is&lt;/span&gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;UInt&lt;/span&gt;.&lt;span style=&#34;color:#c6a0f6&#34;&gt;Type&lt;/span&gt;: &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; decode(&lt;span style=&#34;color:#91d7e3&#34;&gt;UInt&lt;/span&gt;.&lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;, forKey: key) &lt;span style=&#34;color:#c6a0f6&#34;&gt;as&lt;/span&gt;! T
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;case&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;is&lt;/span&gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;UInt8&lt;/span&gt;.&lt;span style=&#34;color:#c6a0f6&#34;&gt;Type&lt;/span&gt;: &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; decode(&lt;span style=&#34;color:#91d7e3&#34;&gt;UInt8&lt;/span&gt;.&lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;, forKey: key) &lt;span style=&#34;color:#c6a0f6&#34;&gt;as&lt;/span&gt;! T
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;case&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;is&lt;/span&gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;UInt16&lt;/span&gt;.&lt;span style=&#34;color:#c6a0f6&#34;&gt;Type&lt;/span&gt;: &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; decode(&lt;span style=&#34;color:#91d7e3&#34;&gt;UInt16&lt;/span&gt;.&lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;, forKey: key) &lt;span style=&#34;color:#c6a0f6&#34;&gt;as&lt;/span&gt;! T
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;case&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;is&lt;/span&gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;UInt32&lt;/span&gt;.&lt;span style=&#34;color:#c6a0f6&#34;&gt;Type&lt;/span&gt;: &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; decode(&lt;span style=&#34;color:#91d7e3&#34;&gt;UInt32&lt;/span&gt;.&lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;, forKey: key) &lt;span style=&#34;color:#c6a0f6&#34;&gt;as&lt;/span&gt;! T
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;case&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;is&lt;/span&gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;UInt64&lt;/span&gt;.&lt;span style=&#34;color:#c6a0f6&#34;&gt;Type&lt;/span&gt;: &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; decode(&lt;span style=&#34;color:#91d7e3&#34;&gt;UInt64&lt;/span&gt;.&lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;, forKey: key) &lt;span style=&#34;color:#c6a0f6&#34;&gt;as&lt;/span&gt;! T
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;case&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;is&lt;/span&gt; Date.&lt;span style=&#34;color:#c6a0f6&#34;&gt;Type&lt;/span&gt;: 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;value&lt;/span&gt; = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; decoder.retrieveValue(forKey: key)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(value)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; decoder._decodeDate(from: value) &lt;span style=&#34;color:#c6a0f6&#34;&gt;as&lt;/span&gt;! T
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;default&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//probably should fatalError this too, but, YOLO.  &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;value&lt;/span&gt; = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; decoder.retrieveValue(forKey: key)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;tmpDecoder&lt;/span&gt; = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; HousePlantDecoder(value)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; type.&lt;span style=&#34;color:#ed8796&#34;&gt;init&lt;/span&gt;(from:tmpDecoder)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;decodeIfPresent&lt;/span&gt;&amp;lt;T&amp;gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; type: T.&lt;span style=&#34;color:#c6a0f6&#34;&gt;Type&lt;/span&gt;, forKey key: Key) &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; -&amp;gt; T? &lt;span style=&#34;color:#c6a0f6&#34;&gt;where&lt;/span&gt; T: Decodable {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#c6a0f6&#34;&gt;guard&lt;/span&gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;contains&lt;/span&gt;(key) &lt;span style=&#34;color:#c6a0f6&#34;&gt;else&lt;/span&gt; { &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;nil&lt;/span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; decode(type, forKey: key)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;nestedContainer&lt;/span&gt;&amp;lt;NestedKey&amp;gt;(keyedBy type: NestedKey.&lt;span style=&#34;color:#c6a0f6&#34;&gt;Type&lt;/span&gt;, forKey key: Key) &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; -&amp;gt; KeyedDecodingContainer&amp;lt;NestedKey&amp;gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;where&lt;/span&gt; NestedKey : CodingKey { &lt;span style=&#34;color:#91d7e3&#34;&gt;fatalError&lt;/span&gt;() }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;nestedUnkeyedContainer&lt;/span&gt;(forKey key: Key) &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; -&amp;gt; any UnkeyedDecodingContainer { &lt;span style=&#34;color:#91d7e3&#34;&gt;fatalError&lt;/span&gt;() }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;superDecoder&lt;/span&gt;(forKey key: Key) &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; -&amp;gt; any Decoder { &lt;span style=&#34;color:#91d7e3&#34;&gt;fatalError&lt;/span&gt;() }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;superDecoder&lt;/span&gt;() &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; -&amp;gt; any Decoder {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        decoder
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Alteratively, the folks who wrote the &lt;a href=&#34;https://github.com/vapor/vapor/blob/3a7da193a2937472b252b8db210897e7abf37b47/Sources/Vapor/Content/PlaintextDecoder.swift#L47&#34;&gt;Vapor PlaintextDecoder&lt;/a&gt; got a little fancy and decoded anything that&amp;rsquo;s a &lt;code&gt;LosslessStringConvertible&lt;/code&gt; in one swoop. (All the &lt;code&gt;FixedWidthInteger&lt;/code&gt;s!) I like it. That&amp;rsquo;s what I&amp;rsquo;ve done in the code linked at the top and bottom of this post. (I wanted to show the code completion code first)&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// in func decode&amp;lt;T&amp;gt;(_ type: T.Type, forKey key: Key)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;case&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;is&lt;/span&gt; LosslessStringConvertible.&lt;span style=&#34;color:#c6a0f6&#34;&gt;Type&lt;/span&gt; :
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;value&lt;/span&gt; = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; decoder.retrieveValue(forKey: key)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;convertible&lt;/span&gt; = T.&lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;as&lt;/span&gt;? LosslessStringConvertible.&lt;span style=&#34;color:#c6a0f6&#34;&gt;Type&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; decoder._decodeLossless(value, ofType:convertible) &lt;span style=&#34;color:#c6a0f6&#34;&gt;as&lt;/span&gt;! T
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            } &lt;span style=&#34;color:#c6a0f6&#34;&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#c6a0f6&#34;&gt;throw&lt;/span&gt; DecodingError.dataCorruptedError(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    forKey: key,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    &lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt;: &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    debugDescription: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Thought &lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;value&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt; could be converted to &lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;type.&lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt; as a LosslessStringConvertible. Something went wrong.&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//add to decoder&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;_decodeLossless&lt;/span&gt;&amp;lt;L: LosslessStringConvertible&amp;gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; value:&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;, ofType: L.&lt;span style=&#34;color:#c6a0f6&#34;&gt;Type&lt;/span&gt;) &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; -&amp;gt; L {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;guard&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;result&lt;/span&gt; = L.&lt;span style=&#34;color:#ed8796&#34;&gt;init&lt;/span&gt;(value) &lt;span style=&#34;color:#c6a0f6&#34;&gt;else&lt;/span&gt; { 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;throw&lt;/span&gt; DecodingError.typeMismatch(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                L.&lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;, 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                DecodingError.Context(codingPath: codingPath, 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                                      debugDescription: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Attempt to decode &lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;value&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt; as &lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;L.&lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt; failed.&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                ) 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; result
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;summary&#34;&gt;Summary&lt;/h2&gt;
&lt;p&gt;Put that all together and one gets a HousePlant struct from a String. the most basic of Decoders, just to prove to myself I get the gist before I go hunting for Decoders on github to break down.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;houseplant_decoder.txt&#34;&gt;Playground Code&lt;/a&gt;&lt;/p&gt;
</description>
    </item>
    
    
    
    <item>
      <title>Date Parsing. Nose wrinkle.</title>
      <link>https://whynotestflight.com/excuses/date-parsing.-nose-wrinkle./</link>
      <pubDate>Fri, 29 Mar 2024 00:00:00 +0000</pubDate>
      
      <guid>https://whynotestflight.com/excuses/date-parsing.-nose-wrinkle./</guid>
      <description>&lt;ul&gt;
&lt;li&gt;&lt;input checked=&#34;&#34; disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; remember how to inspect strings in general&lt;/li&gt;
&lt;li&gt;&lt;input disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; decide about Dates specifically &amp;lt;=&lt;/li&gt;
&lt;li&gt;&lt;input disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; write a really really simple decoder to walk through the process&lt;/li&gt;
&lt;li&gt;&lt;input disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; inspect other peoples decoders&lt;/li&gt;
&lt;li&gt;&lt;input disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; write the string -&amp;gt; tree step for SimpleCoder&lt;/li&gt;
&lt;li&gt;&lt;input disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; finish the full decoder (with round trip tests)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The test &lt;code&gt;HousePlant&lt;/code&gt; from the &lt;a href=&#34;https://whynotestflight.com/excuses/wait-how-do-i-scan-text-again/&#34;&gt;last post&lt;/a&gt; just totally punted on parsing dates, but I know I want to use them. So now what?&lt;/p&gt;
&lt;p&gt;First step is to be clear on what a &lt;code&gt;Date&lt;/code&gt; type is and what it isn&amp;rsquo;t. As we saw &lt;a href=&#34;https://whynotestflight.com/excuses/and-what-can-i-make-a-custom-encoder-do/#fixing-the-dates&#34;&gt;when writing the encoder&lt;/a&gt;, the default &lt;code&gt;Codable&lt;/code&gt; representation for &lt;code&gt;Date&lt;/code&gt; is &lt;code&gt;timeIntervalSinceReferenceDate&lt;/code&gt; because that is what a &lt;code&gt;Date&lt;/code&gt;&amp;rsquo;s core storage is (&lt;a href=&#34;https://github.com/apple/swift-corelibs-foundation/blob/1dac1132d49b0ee4213ac89473019cae8a608b5c/Sources/Foundation/Date.swift#L20&#34;&gt;core&lt;/a&gt; | &lt;a href=&#34;https://github.com/apple/swift-foundation/blob/69a6e9f4902f5043a89fbfa1da0e89a1ffe367fe/Sources/FoundationEssentials/Date.swift#L33&#34;&gt;FoundationEssentials&lt;/a&gt; ), a &lt;a href=&#34;https://developer.apple.com/documentation/foundation/timeinterval&#34;&gt;TimeInterval&lt;/a&gt;. And what&amp;rsquo;s a TimeInterval? &lt;a href=&#34;https://github.com/apple/swift-corelibs-foundation/blob/77af9c5a984f40e186c0ba127cff88f2a2588c15/Sources/Foundation/NSDate.swift#L12&#34;&gt;A type alias for a Double&lt;/a&gt; representing seconds.&lt;/p&gt;
&lt;p&gt;Any other representation of a &lt;code&gt;Date&lt;/code&gt; provided by a formatter is a convenience. &lt;a href=&#34;https://developer.apple.com/documentation/foundation/calendar&#34;&gt;Calendar&lt;/a&gt; and &lt;a href=&#34;https://swiftpackageindex.com/search?query=Date&#34;&gt;other libraries&lt;/a&gt; better serve  working with days, hours, months (little d dates) as first-order concepts.  One cannot have a &lt;code&gt;Date&lt;/code&gt; with nil for hours. That makes no sense. &lt;code&gt;Date&lt;/code&gt; has no Optional &amp;ldquo;hours&amp;rdquo; parameter. &lt;code&gt;Date&lt;/code&gt; is a unidimensional time coordinate; it must be specific.  One can represent spotty calendar style information with &lt;a href=&#34;https://developer.apple.com/documentation/foundation/datecomponents&#34;&gt;&lt;code&gt;DateComponents&lt;/code&gt;&lt;/a&gt;, &lt;em&gt;not&lt;/em&gt; &lt;code&gt;Date&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The various date formatters one can use in Swift do an excellent job of creating these time coordinates we call a &lt;code&gt;Date&lt;/code&gt; from &lt;code&gt;Strings&lt;/code&gt; and vice versa. However, it could be easy to end up very frustrated with them if in fact one is trying to do with&lt;code&gt;Date&lt;/code&gt; things that would be much better served by a different API. (For even more on this topic see &lt;a href=&#34;https://forums.swift.org/search?q=%20SE-0329&#34;&gt;conversations around SE-0329&lt;/a&gt;) (&lt;a href=&#34;https://vimeo.com/865876497&#34;&gt;also this NSSpain X Dave DeLong talk&lt;/a&gt;)&lt;/p&gt;
&lt;p&gt;As of 2021 there are new versions of theses formatters in &lt;code&gt;Foundation&lt;/code&gt;. The WWDC21 video &amp;ldquo;What&amp;rsquo;s new in Foundation&amp;rdquo; (&lt;a href=&#34;https://developer.apple.com/wwdc21/10109?time=869&#34;&gt;14:29&lt;/a&gt;) shows both the old style and the new and explains the motivation.&lt;/p&gt;
&lt;p&gt;The WWDC22 RegEx videos both show working with the new formatter in the context of a RegEx.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://developer.apple.com/videos/play/wwdc2022/110357/?time=693&#34;&gt;https://developer.apple.com/videos/play/wwdc2022/110357/?time=693&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://developer.apple.com/videos/play/wwdc2022/110358?time=314&#34;&gt;https://developer.apple.com/videos/play/wwdc2022/110358?time=314&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;code&gt;swift-foundation&lt;/code&gt; has public implementations.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/apple/swift-foundation/blob/71cf0809cc713ea25dfe569ea530dbb8d1b963e1/Sources/FoundationEssentials/Formatting/ParseStrategy.swift#L15&#34;&gt;ParseStrategy protocol definition&lt;/a&gt; (FoundationEssentials)&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/apple/swift-foundation/blob/71cf0809cc713ea25dfe569ea530dbb8d1b963e1/Sources/FoundationInternationalization/Formatting/Date/DateParseStrategy.swift#L20&#34;&gt;ParseStrategy Extension on Date&lt;/a&gt; (FoundationInternationalization)&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/apple/swift-foundation/blob/71cf0809cc713ea25dfe569ea530dbb8d1b963e1/Sources/FoundationInternationalization/Formatting/Date/ICUDateFormatter.swift#L27&#34;&gt;ICUDateFormatter&lt;/a&gt; Internal class doing the work. (FoundationInternationalization)&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/apple/swift-foundation/blob/71cf0809cc713ea25dfe569ea530dbb8d1b963e1/Sources/FoundationInternationalization/Formatting/Date/DateFormatString.swift#L19&#34;&gt;Date.FormatString definition&lt;/a&gt; (FoundationInternationalization)&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/apple/swift-foundation/blob/71cf0809cc713ea25dfe569ea530dbb8d1b963e1/Sources/FoundationInternationalization/Formatting/Date/DateFormatString.swift#L40&#34;&gt;extension Date.FormatString&lt;/a&gt; (FoundationInternationalization)&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/apple/swift-foundation/blob/872c7e7fd25a476e7dcefc677413d53a16c4a4c4/Sources/FoundationInternationalization/Formatting/Date/DateFieldSymbol.swift&#34;&gt;DateFieldSymbol&lt;/a&gt; (FoundationInternationalization)&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/apple/swift-foundation/blob/c2ad2dd6acf0a21ca3199d94e6391127198c58ea/Sources/FoundationInternationalization/Formatting/Date/DateFormatStyle.swift&#34;&gt;DateFormatStyle&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/apple/swift-foundation/blob/71cf0809cc713ea25dfe569ea530dbb8d1b963e1/Sources/FoundationInternationalization/Formatting/Date/Date%2BVerbatimFormatStyle.swift&#34;&gt;VerbatimFormatStyle&lt;/a&gt; (FoundationInternationalization)&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/apple/swift-foundation/blob/71cf0809cc713ea25dfe569ea530dbb8d1b963e1/Sources/FoundationInternationalization/Formatting/Date/Date%2BISO8601FormatStyleParsing.swift#L95&#34;&gt;Date.ISO8601FormatStyle&lt;/a&gt; (FoundationInternationalization)&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/apple/swift-evolution/blob/1b0b339bc3072a83b5a6a529ae405a0f076c7d5d/proposals/0350-regex-type-overview.md?plain=1#L71&#34;&gt;Date parsing as mentioned in RegEx Pitch (5.7)&lt;/a&gt; (swift-evolution)&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/apple/swift-evolution/blob/1b0b339bc3072a83b5a6a529ae405a0f076c7d5d/proposals/0357-regex-string-processing-algorithms.md?plain=1&#34;&gt;Regex String Processing Algorithms&lt;/a&gt; (swift-evolution)&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;formatstyle&#34;&gt;FormatStyle&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;FormatStyle&lt;/code&gt; seems to be designed for UI representation, making sure that the user&amp;rsquo;s settings stay in charge of how a &lt;code&gt;Date&lt;/code&gt; gets displayed. As a result a &lt;code&gt;FormatStyle&lt;/code&gt; works differently depending on the device&amp;rsquo;s settings and localization. Output will behave a bit unpredictably to the developer. For example, 24 hour time display gets decided by the user&amp;rsquo;s system settings, not the developer.  On the other hand, it also provides some pretty generous parsers as demonstrated below.&lt;/p&gt;
&lt;p&gt;My Playground and Package Manager for some reason had differing opinions about my locale settings? (TODO?) I could have gotten more control by adding an explicit Locale (e.g. &lt;code&gt;.locale(Locale(identifier: &amp;quot;en_US&amp;quot;))&lt;/code&gt;), but I decided to roll with it to see the different behaviors.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//Computer settings PDT. &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//In Playground. Fails in package until date string changed to 03/28/2024&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;basicFormatStyle&lt;/span&gt; = Date.FormatStyle()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;basicDate&lt;/span&gt; = basicFormatStyle.parse(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;28/03/2024 03:12 PM&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;basicStringFromDate&lt;/span&gt; = basicFormatStyle.format(basicDate)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;date:&amp;#34;&lt;/span&gt;, basicDate, &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;string:&amp;#34;&lt;/span&gt;, basicStringFromDate)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//date: 2024-03-28 22:12:00 +0000 string: 28/03/2024, 3:12 PM&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;If time doesn&amp;rsquo;t matter, one can ignore it by telling the format style which fields you do care about. Order doesn&amp;rsquo;t matter. Order will be determined by the Locale. Notice in the print out there still is a time, but its midnight in the device&amp;rsquo;s time zone relative to UTC, not the time from the String.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//Computer settings PDT. &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//In Playground. Fails in package until date string changed to month leading&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;dateOnlyStyle&lt;/span&gt;:Date.FormatStyle = .dateTime.year().day().month()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;dateOnlyDate&lt;/span&gt; = dateOnlyStyle.parse(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;28/03/2024 03:12 PM&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;dateOnlyStringFromDate&lt;/span&gt; = dateOnlyStyle.format(dateOnlyDate)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;date:&amp;#34;&lt;/span&gt;, dateOnlyDate, &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;string:&amp;#34;&lt;/span&gt;, dateOnlyStringFromDate)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//date: 2024-03-28 07:00:00 +0000 string: 28 Mar 2024&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;A FormatStyle ends up being super chill about the text it will take in. It took all the following text inputs
(Playground examples. Switched to month leading in Package Manger. There does not seem to be a way to make a super chill year-leading formatter? Where does that?)&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;28/03/2024
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;28 Mar 2024
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;28-03-2024
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;28-Mar-2024
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;28   .-/  03   .-/ 2024
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;But not&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;28 fhujsflh 03 jifoalgf 2024
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;So it does seem to be limited to &amp;ldquo;the usual suspects&amp;rdquo; in terms of date delimiters.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ve been showing the showing the shortcuts. The full initializer looks like&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Date.FormatStyle(date: Date.FormatStyle.DateStyle?, 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                 time: Date.FormatStyle.TimeStyle?, 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                 locale: Locale, 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                 calendar: Calendar, 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                 timeZone: TimeZone, 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                 capitalizationContext: FormatStyleCapitalizationContext)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;For example (&lt;a href=&#34;https://forums.swift.org/t/new-date-formatstyle-anyway-to-do-24-hour/52994/11&#34;&gt;why this&lt;/a&gt;)&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;customFormat&lt;/span&gt; = Date.FormatStyle(date: .complete, 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                                   time: .complete, 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                                   locale: Locale(identifier: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;zh_Hans_CN&amp;#34;&lt;/span&gt;), 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                                   calendar: Calendar(identifier: .chinese), 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                                   timeZone: TimeZone(identifier: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;UTC&amp;#34;&lt;/span&gt;)&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;!&lt;/span&gt;, 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                                   capitalizationContext: .beginningOfSentence)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//Text(Date.now, format:Self.customFormat) &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//=&amp;gt; Second Month 19, 2024(jia-chen) at 21:37:17&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// when it was Thursday Mar 28 14:37:17 and system time was set to 24hr time. &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;iso8601formatstyle&#34;&gt;ISO8601FormatStyle&lt;/h2&gt;
&lt;p&gt;If less chill is desired, one can go for the built in ISO8601 format.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;dateString&lt;/span&gt; = &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;20240312 03:12:10&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;myDateFormat&lt;/span&gt;:Date.ISO8601FormatStyle = .iso8601.year().month().day().dateSeparator(.omitted)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;myDate&lt;/span&gt; = myDateFormat.parse(dateString2)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;stringFromDate&lt;/span&gt; = myDateFormat.format(myDate)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;date:&amp;#34;&lt;/span&gt;, myDate, &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;string:&amp;#34;&lt;/span&gt;, stringFromDate)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//date: 2024-03-12 00:00:00 +0000 string: 20240312&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;With time omitted from the format, again the parser will just ignore it. Overall the &lt;code&gt;ISO8601FormatStyle&lt;/code&gt; assumes the date data will be generated by machines and be read by machines. It has very limited configuration. It&amp;rsquo;s not interested in being a good sport. That&amp;rsquo;s not its job.&lt;/p&gt;
&lt;h2 id=&#34;verbatimformatstyle-and-dateformatstring&#34;&gt;VerbatimFormatStyle and DateFormatString&lt;/h2&gt;
&lt;p&gt;If one wants less chill like with &lt;code&gt;ISO8601FormatStyle&lt;/code&gt;, but in a custom style, &lt;code&gt;VerbatimFormatStyle&lt;/code&gt; combined with a &lt;code&gt;DateFormatString&lt;/code&gt; provides a similar functionality.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//for some reason Playground balks when not dynamic var&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;isoFormatString&lt;/span&gt;:Date.FormatString {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;year: .defaultDigits&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;-&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;month: .twoDigits&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;-&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;day: .twoDigits&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;verbatimFormat&lt;/span&gt;:Date.VerbatimFormatStyle = .&lt;span style=&#34;color:#ed8796&#34;&gt;init&lt;/span&gt;(format: isoFormatString, timeZone: TimeZone.gmt, calendar: Calendar.current)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//need to drop down into the parseStrategy directly &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;verbatimDate&lt;/span&gt; = verbatimFormat.parseStrategy.parse(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;2024-03-12&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;stringFromVDate&lt;/span&gt; = verbatimFormat.format(myDate)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//date: 2024-03-12 00:00:00 +0000 string: 2024-03-12&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This is exactly how to get 24 hour time, independent of the system settings.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;withTime&lt;/span&gt;:Date.FormatString { &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;year: .defaultDigits&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;-&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;month: .twoDigits&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;-&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;day: .twoDigits&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;hour: .twoDigits&lt;span style=&#34;color:#a6da95&#34;&gt;(&lt;/span&gt;clock: .twentyFourHour, hourCycle: .zeroBased&lt;span style=&#34;color:#a6da95&#34;&gt;))&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;minute: .twoDigits&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;second: .defaultDigits&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;timeZone: .identifier&lt;span style=&#34;color:#a6da95&#34;&gt;(&lt;/span&gt;.short&lt;span style=&#34;color:#a6da95&#34;&gt;))&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;verbatimFormatWithTime&lt;/span&gt;:Date.VerbatimFormatStyle = .&lt;span style=&#34;color:#ed8796&#34;&gt;init&lt;/span&gt;(format: withTime, timeZone: TimeZone.gmt, calendar: Calendar.current)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(verbatimFormatWithTime.format(Date.now))
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The &lt;code&gt;VerbatimFormatStyle&lt;/code&gt; does not appear to work with &lt;code&gt;Date.FormatString&lt;/code&gt; literals (FB13700896, &lt;a href=&#34;https://forums.swift.org/t/date-parsestrategy-datestring-overload/70649&#34;&gt;semi-embarrassing forum post&lt;/a&gt; (plenty of those)), but pure &lt;code&gt;ParseStrategy&lt;/code&gt; approaches do.&lt;/p&gt;
&lt;p&gt;If one wants flexibility and a custom style&amp;hellip; well that&amp;rsquo;s where I&amp;rsquo;d abandon &lt;code&gt;Date&lt;/code&gt; for &lt;code&gt;DateComponent&lt;/code&gt; and pull out &lt;code&gt;RegExBuilder&lt;/code&gt;. Maybe even make some &lt;a href=&#34;https://developer.apple.com/documentation/swift/customconsumingregexcomponent&#34;&gt;custom components&lt;/a&gt;. OOOooo or maybe a custom scanner&amp;hellip; no this is 2024 its gotta be ML&amp;hellip; But as I officially have too many projects going and Decoders do not require the ability to take human generated input, not today.&lt;/p&gt;
&lt;h2 id=&#34;parsestrategy&#34;&gt;ParseStrategy&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;Date&lt;/code&gt; initializers can now take a &lt;code&gt;ParseStrategy&lt;/code&gt;. You can roll your own with a &lt;code&gt;Date.FormatString&lt;/code&gt;, or extract one from an existing &lt;code&gt;Date.FormatStyle&lt;/code&gt; (&lt;code&gt;myFormatStyle.parseStrategy.format&lt;/code&gt;). Like &lt;code&gt;VerbatimFormatStyle&lt;/code&gt; they don&amp;rsquo;t provide flexibility.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//THIS CODE DOES NOT WORK IN PLAYGROUNDS&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;testDateParsing&lt;/span&gt;() &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;dashString&lt;/span&gt;:Date.FormatString = &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&amp;#39;y-M-d&amp;#39;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;strategy&lt;/span&gt; = Date.ParseStrategy(format:  dashString, timeZone: .gmt)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;date&lt;/span&gt; = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; Date(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;2024-03-12&amp;#34;&lt;/span&gt;, strategy: strategy)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;newDate:&amp;#34;&lt;/span&gt;, date)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//newDate 2024-03-12 00:00:00 +0000&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;formatString&lt;/span&gt; = strategy.format &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//returns the format string.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(formatString)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//&amp;#39;&amp;#39;y-M-d&amp;#39;&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;date2&lt;/span&gt; = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; strategy.parse(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;2024-03-12&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    XCTAssertEqual(date, date2)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;In this example I used a &lt;code&gt;Date.FormatString&lt;/code&gt; literal, but THEY ARE NOT IDENTICAL to the old &lt;a href=&#34;https://www.advancedswift.com/date-formatter-cheatsheet-formulas-swift/&#34;&gt;&lt;code&gt;DateFormatter&lt;/code&gt; literals&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;They&amp;rsquo;re going to take some getting used to.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&#34;https://github.com/apple/swift-foundation/blob/872c7e7fd25a476e7dcefc677413d53a16c4a4c4/Sources/FoundationInternationalization/Formatting/Date/DateFieldSymbol.swift#L73&#34;&gt;Definition y&lt;/a&gt; (current year)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&#34;https://github.com/apple/swift-foundation/blob/872c7e7fd25a476e7dcefc677413d53a16c4a4c4/Sources/FoundationInternationalization/Formatting/Date/DateFieldSymbol.swift#L122&#34;&gt;Definition Y&lt;/a&gt; (week of year?)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;works: &lt;code&gt;&amp;quot;&#39;y&#39;-&#39;MM&#39;-&#39;dd&#39; &#39;HH&#39;:&#39;mm&#39;:&#39;ss&#39;&amp;quot;&lt;/code&gt;, fails: &lt;code&gt;&amp;quot;y&#39;-&#39;MM&#39;-&#39;dd&#39; &#39;HH&#39;:&#39;mm&#39;:&#39;ss&amp;quot;&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;When the date string is &lt;code&gt;let dateString = &amp;quot;20240312031210&amp;quot;&lt;/code&gt; the string has to be &lt;code&gt;&amp;quot;&#39;yyyyMMddHHmmss&#39;&amp;quot;&lt;/code&gt; and the full initializer has to have the year as &lt;code&gt;\(year: .extended(minimumLength: 4))&lt;/code&gt; as &lt;code&gt;.defaultdigits&lt;/code&gt; does not work.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If one wanted to extract a format string to pass it around, it would need a little massaging to get back into proper &lt;code&gt;Date.FormatString&lt;/code&gt; condition.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;formatString&lt;/span&gt;:Date.FormatString {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    Date.FormatString(stringLiteral: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;someFormat.parseStrategy.format&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#39;&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;strategy&lt;/span&gt; = Date.ParseStrategy(format:  formatString, timeZone: .gmt)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;date&lt;/span&gt; = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; Date(dateString, strategy: strategy)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;example-for-the-decoder&#34;&gt;Example for the Decoder&lt;/h2&gt;
&lt;p&gt;My first crack at decoding a date actually went straight for initializing a &lt;code&gt;ParseStrategy&lt;/code&gt; with a &lt;code&gt;Date.FormatString.&lt;/code&gt; Which strategy depended on whether the time was included (based on presence of colon).&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;_decodeDate&lt;/span&gt;(from value:&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;) &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; -&amp;gt; Date {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//gmt to make sure time fields are 0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;strategy&lt;/span&gt; = &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; value.&lt;span style=&#34;color:#91d7e3&#34;&gt;contains&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;:&amp;#34;&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//strings can work too, not identical to DateFormatter but similar&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                        Date.ParseStrategy(format: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&amp;#39;yyyy-MM-dd&amp;#39; &amp;#39;HH:mm:ss&amp;#39;&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                                            timeZone: .gmt)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    } &lt;span style=&#34;color:#c6a0f6&#34;&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                        Date.ParseStrategy(format: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;year: .defaultDigits&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;-&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;month: .twoDigits&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;-&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;day: .twoDigits&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;, 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                                           timeZone: .gmt)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;guard&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;date&lt;/span&gt; = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt;? Date(value, strategy: strategy) &lt;span style=&#34;color:#c6a0f6&#34;&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;throw&lt;/span&gt; DecodingError.dataCorrupted(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            .&lt;span style=&#34;color:#ed8796&#34;&gt;init&lt;/span&gt;(codingPath: [], debugDescription: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;String not in expected &lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;strategy.format&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt; format.&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        )
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; date
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;On second pass I changed the code to use the &lt;code&gt;ISO8601FormatStyle&lt;/code&gt; because that&amp;rsquo;s &lt;a href=&#34;https://developer.apple.com/documentation/foundation/date/iso8601formatstyle&#34;&gt;the industry standard&lt;/a&gt;. Additionally, I decided to require a time zone (distance from UTC as ±HH:mm or Z if UTC) if a time is also included. An Encoder should be able to provide that no problem.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;_decodeDate&lt;/span&gt;(from value:&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;) &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; -&amp;gt; Date {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//gmt (&amp;#34;Z&amp;#34;)is the default. &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;format&lt;/span&gt; = &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; value.&lt;span style=&#34;color:#91d7e3&#34;&gt;contains&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;:&amp;#34;&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    Date.ISO8601FormatStyle.iso8601
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//.dateTimeSeparator(.space)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                } &lt;span style=&#34;color:#c6a0f6&#34;&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    Date.ISO8601FormatStyle.iso8601
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                        .year().month().day()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;guard&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;date&lt;/span&gt; = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt;? format.parse(value) &lt;span style=&#34;color:#c6a0f6&#34;&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;throw&lt;/span&gt; DecodingError.dataCorrupted(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            .&lt;span style=&#34;color:#ed8796&#34;&gt;init&lt;/span&gt;(codingPath: [], debugDescription: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;String not in expected &lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;format.parseStrategy&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt; format.&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        )
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; date
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;I could try to be a lot more gracious with what strings I&amp;rsquo;ll accept, but I&amp;rsquo;m choosing not to be. When writing a Decoder, it&amp;rsquo;s important to know if the data will be coming from:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;user input,&lt;/li&gt;
&lt;li&gt;only your own Encoder,&lt;/li&gt;
&lt;li&gt;or someone else&amp;rsquo;s serialization process&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The question becomes: is a badly formatted date something to be gracious about, or an alarm that the data can&amp;rsquo;t be trusted. I wanted to think about how to accept more than one format style, but not go full general purpose calendar event storage.&lt;/p&gt;
&lt;h2 id=&#34;summary&#34;&gt;Summary&lt;/h2&gt;
&lt;p&gt;Good. Enough. Next post, a super basic Decoder.&lt;/p&gt;
</description>
    </item>
    
    
    
    <item>
      <title>Wait, how do I scan text again?</title>
      <link>https://whynotestflight.com/excuses/wait-how-do-i-scan-text-again/</link>
      <pubDate>Wed, 27 Mar 2024 00:00:00 +0000</pubDate>
      
      <guid>https://whynotestflight.com/excuses/wait-how-do-i-scan-text-again/</guid>
      <description>&lt;p&gt;The encoder spun our data out into a thread using serialization. A decoder crochets that thread back into an object.&lt;/p&gt;
&lt;p&gt;If the data coming into the decoder is highly structured and narrow in scope it can actually be kind of relaxing to parse. In the Swift Talk decoder example (&lt;a href=&#34;https://talk.objc.io/episodes/S01E349-routing-with-codable-decoding&#34;&gt;video&lt;/a&gt; (paywall) | &lt;a href=&#34;https://github.com/objcio/S01E349-routing-with-codable-decoding&#34;&gt;github&lt;/a&gt;) the parsing ends up being pretty straight forward because their encoder only takes in a &lt;code&gt;Route&lt;/code&gt;, and the decoder only produce a &lt;code&gt;Route&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The general purpose mayhem of taking in any Codable that SimpleCoder performs is the whole point of an Encoder/Decoders pair (they are about the format, not the type) but it&amp;rsquo;s a lot to tackle in one bite. I&amp;rsquo;m not even using brackets to help calculate object relationships. Oof.&lt;/p&gt;
&lt;p&gt;As a result making the decoder will be a much slower job.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;input disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; remember how to inspect strings in general&lt;/li&gt;
&lt;li&gt;&lt;input disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; decide about Dates specifically&lt;/li&gt;
&lt;li&gt;&lt;input disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; write a really really simple decoder to walk through the process&lt;/li&gt;
&lt;li&gt;&lt;input disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; inspect other peoples decoders&lt;/li&gt;
&lt;li&gt;&lt;input disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; write the string -&amp;gt; tree step for SimpleCoder&lt;/li&gt;
&lt;li&gt;&lt;input disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; finish the full decoder (with round trip tests)&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;in-this-post&#34;&gt;In this post&lt;/h3&gt;
&lt;p&gt;First on the list, I&amp;rsquo;m going to catalog all the ways I know how to scan strings for information.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;String.builtinThing (0.000195)&lt;/li&gt;
&lt;li&gt;Moving the index (0.000113)&lt;/li&gt;
&lt;li&gt;Regex (\: 0.000399, builder: 0.000176)&lt;/li&gt;
&lt;li&gt;Scanner (v1 0.0000439, v2 0.0000512)&lt;/li&gt;
&lt;li&gt;Scanner + Dynamic Sequence (0.0000261)&lt;/li&gt;
&lt;li&gt;Custom char scanner (0.0000246)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The number in parenthesis is the average time to turn one example string into a Dictionary according to my XCTest set up. I&amp;rsquo;m focused on their relative order of magnitude.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;testStaticParserJ&lt;/span&gt;() &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        measure {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;do&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;dictJ&lt;/span&gt; = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; HousePlantTest.parse_charScanner4(serializedHousePlant)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            } &lt;span style=&#34;color:#c6a0f6&#34;&gt;catch&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#91d7e3&#34;&gt;fatalError&lt;/span&gt;()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;I&amp;rsquo;m going to delay talking about making a &lt;a href=&#34;https://en.wikipedia.org/wiki/Parser_combinator&#34;&gt;Parser Combinator&lt;/a&gt; or other more substantial parser class because that would be complete overkill for a &amp;ldquo;MyFirstDecoder&amp;rdquo; Decoder, even for me.&lt;/p&gt;
&lt;h2 id=&#34;using-built-in-string-functions&#34;&gt;Using built in String functions&lt;/h2&gt;
&lt;p&gt;Let&amp;rsquo;s imagine there is a &lt;code&gt;HousePlant&lt;/code&gt; struct and an encoded example. As long as we can get that string into a &lt;code&gt;Dictionary&amp;lt;String, String&amp;gt;&lt;/code&gt;, we can make a &lt;code&gt;HousePlant&lt;/code&gt; out of it. (I&amp;rsquo;m going to punt on Date parsing for now)&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//Playground style&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;HousePlant&lt;/span&gt;:Codable {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;commonName&lt;/span&gt;:&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;whereAcquired&lt;/span&gt;:&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;?
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;dateAcquired&lt;/span&gt;:&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;dateOfDeath&lt;/span&gt;:&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;?
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;parse&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; inputString:&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;) &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; -&amp;gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;Dictionary&lt;/span&gt;&amp;lt;&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;,&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;&amp;gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;fullKeyValueList&lt;/span&gt; = inputString.&lt;span style=&#34;color:#91d7e3&#34;&gt;split&lt;/span&gt;(separator: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;/&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;result&lt;/span&gt;:&lt;span style=&#34;color:#91d7e3&#34;&gt;Dictionary&lt;/span&gt;&amp;lt;&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;,&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;&amp;gt; = [:]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; fullKeyValueList.&lt;span style=&#34;color:#91d7e3&#34;&gt;reduce&lt;/span&gt;(into: result){ result, item &lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;kvSplit&lt;/span&gt; = item.&lt;span style=&#34;color:#91d7e3&#34;&gt;split&lt;/span&gt;(separator: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;:&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;key&lt;/span&gt; = &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;(kvSplit[&lt;span style=&#34;color:#f5a97f&#34;&gt;0&lt;/span&gt;]).trimmingCharacters(&lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt;: .whitespacesAndNewlines)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;value&lt;/span&gt; = &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;(kvSplit[&lt;span style=&#34;color:#f5a97f&#34;&gt;1&lt;/span&gt;]).trimmingCharacters(&lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt;: .whitespacesAndNewlines)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            result[key] = value
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;extension&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;HousePlant&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;init&lt;/span&gt;?(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; inputString:&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;guard&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;dictionary&lt;/span&gt; = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt;? HousePlant.parse(inputString) &lt;span style=&#34;color:#c6a0f6&#34;&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;nil&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;made dictionary&amp;#34;&lt;/span&gt;, dictionary)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;cN&lt;/span&gt; = dictionary[&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;commonName&amp;#34;&lt;/span&gt;] {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;commonName&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;.commonName = cN
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        } &lt;span style=&#34;color:#c6a0f6&#34;&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;nil&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;dA&lt;/span&gt; = dictionary[&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;dateAcquired&amp;#34;&lt;/span&gt;] {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;dateAcquired&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;.dateAcquired = dA
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        } &lt;span style=&#34;color:#c6a0f6&#34;&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;nil&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;.whereAcquired = dictionary[&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;whereAcquired&amp;#34;&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;.dateOfDeath = dictionary[&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;dateOfDeath&amp;#34;&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;serializedHousePlant&lt;/span&gt; = &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;commonName:spider plant/whereAcquired:Trader Joe&amp;#39;s/dateAcquired: 2024-03-12&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;housePlant&lt;/span&gt; = HousePlant(serializedHousePlant)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(housePlant ?? &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;no plant&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;a href=&#34;https://developer.apple.com/documentation/swift/string&#34;&gt;String&lt;/a&gt; and &lt;a href=&#34;https://developer.apple.com/documentation/swift/stringprotocol&#34;&gt;StringProtocol&lt;/a&gt; have many built in functions to do basic scanning. In this case a &lt;a href=&#34;https://developer.apple.com/documentation/swift/string/split(separator:maxsplits:omittingemptysubsequences:)&#34;&gt;split&lt;/a&gt; and a &lt;a href=&#34;https://developer.apple.com/documentation/swift/stringprotocol/trimmingcharacters(in:)/&#34;&gt;trim&lt;/a&gt; were good enough.&lt;/p&gt;
&lt;h2 id=&#34;move-the-index&#34;&gt;Move the index&lt;/h2&gt;
&lt;p&gt;The current parser works, but it could get into trouble. Imagine our starting text was instead&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;commonName: spider plant /whereAcquired :Trader Joe&amp;#39;s/dateAcquired: 2024-03-12 16:12:07&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The value contains a delimiter.&lt;/p&gt;
&lt;p&gt;One way to accommodate strings with the delimiter character in them is to just stop at the first example of the delimiter. The quick and dirty way to do that would be to update the the current code to &lt;code&gt;.split(separator: &amp;quot;:&amp;quot;, maxSplits: 1)&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Alternatively we can switch to moving through the string with a &lt;a href=&#34;https://stackoverflow.com/questions/39676939/how-does-string-index-work-in-swift&#34;&gt;&lt;code&gt;String.Index&lt;/code&gt;&lt;/a&gt;. An advantage being there&amp;rsquo;s no risk of throwing an index out of bounds error anymore.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;parse_stringIndex&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; inputString:&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;) &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; -&amp;gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;Dictionary&lt;/span&gt;&amp;lt;&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;,&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;&amp;gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;fullKeyValueList&lt;/span&gt; = inputString.&lt;span style=&#34;color:#91d7e3&#34;&gt;split&lt;/span&gt;(separator: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;/&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;result&lt;/span&gt;:&lt;span style=&#34;color:#91d7e3&#34;&gt;Dictionary&lt;/span&gt;&amp;lt;&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;,&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;&amp;gt; = [:]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; fullKeyValueList.&lt;span style=&#34;color:#91d7e3&#34;&gt;reduce&lt;/span&gt;(into: result){ result, item &lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;firstColonIndex&lt;/span&gt; = item.firstIndex(of: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;:&amp;#34;&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;key&lt;/span&gt; = item
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    .&lt;span style=&#34;color:#c6a0f6&#34;&gt;prefix&lt;/span&gt;(upTo: firstColonIndex)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    .trimmingCharacters(&lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt;: .whitespacesAndNewlines)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;value&lt;/span&gt; = item
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    .&lt;span style=&#34;color:#91d7e3&#34;&gt;suffix&lt;/span&gt;(from: item.index(firstColonIndex, offsetBy: &lt;span style=&#34;color:#f5a97f&#34;&gt;1&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    .trimmingCharacters(&lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt;: .whitespacesAndNewlines)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                result[&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;(key)] = &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;(value)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            } &lt;span style=&#34;color:#c6a0f6&#34;&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#c6a0f6&#34;&gt;throw&lt;/span&gt; HousePlantError.notAKeyValuePair
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;regex-example&#34;&gt;RegEx example&lt;/h2&gt;
&lt;p&gt;I love regular expressions, although &lt;a href=&#34;https://stackoverflow.com/questions/764247/why-are-regular-expressions-so-controversial&#34;&gt;some do not&lt;/a&gt;. Understanding RegEx as a &lt;a href=&#34;https://swtch.com/~rsc/regexp/regexp1.html&#34;&gt;DSL for writing lexical analysis state machines&lt;/a&gt; improved how I use them. I&amp;rsquo;ve documented using them in Swift before to detect the header of a USD file (&lt;a href=&#34;https://whynotestflight.com/excuses/hello-usd-part-13-test-test-test/&#34;&gt;RegExBuilder version&lt;/a&gt;, &lt;a href=&#34;https://whynotestflight.com/excuses/hello-usd-part-14-now-to-get-github-to-run-the-tests/&#34;&gt;back tracking to a literal&lt;/a&gt;)&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;SIDEBAR: To see the pros detect a header look at the Package Manger &lt;a href=&#34;https://github.com/apple/swift-package-manager/blob/b49a22787a5873f8f67e5de48ae3ba7499bfb9d8/Sources/PackageLoading/ToolsVersionParser.swift&#34;&gt;ToolsVersionParser&lt;/a&gt;. It&amp;rsquo;s a 685 line file.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The non-regex version works fine for this, so I don&amp;rsquo;t think I&amp;rsquo;d actually bother in a real project.&lt;/p&gt;
&lt;p&gt;I typically start making a regex by opening &lt;a href=&#34;https://regex101.com&#34;&gt;https://regex101.com&lt;/a&gt;. The scanner will need a to &lt;a href=&#34;https://www.regular-expressions.info/captureall.html&#34;&gt;capture a repeated group&lt;/a&gt;. The below examples were created with the &lt;a href=&#34;https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions#advanced_searching_with_flags&#34;&gt;/gm flags&lt;/a&gt; and the original test string.&lt;/p&gt;
&lt;p&gt;Here&amp;rsquo;s the evolution process:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;([^\/:]+)&lt;/code&gt; : works. simple. Tada. (one or more &amp;ldquo;not / or :&amp;rdquo; greedy.)(every item, could interleave.)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;(?:(?:\A|\/)([^\/]+)(?:$|\/))&lt;/code&gt; : Explicit &amp;ldquo;between /&amp;rdquo;, consumes the /. Doesn&amp;rsquo;t grab middle groups.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;(?&amp;lt;=\/|^)(.*?)(?=\/|$)&lt;/code&gt; : look ahead and behind version switch to &lt;code&gt;.*?&lt;/code&gt; (not greedy anything until delimiter)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;(?&amp;lt;=\/|^)(?:(.*?):(.*?))(?=\/|$)&lt;/code&gt; : splits&lt;/li&gt;
&lt;li&gt;&lt;code&gt;(?:^|\A|\G)(.*?)(?:\/|$)&lt;/code&gt; :&lt;a href=&#34;https://forums.swift.org/t/swift-regex-lookbehind/58477/6&#34;&gt;remove lookbehind&lt;/a&gt;, no split&lt;/li&gt;
&lt;li&gt;&lt;code&gt;(?:^|\A|\G)(?:(.+?):(.+?))(?:\/|$)&lt;/code&gt; : return the split&lt;/li&gt;
&lt;li&gt;&lt;code&gt;(?:^|\A|\G)(?:\s*(.+?)\s*:\s*(.+?)\s*)(?:\/|$)&lt;/code&gt; : trim white space&lt;/li&gt;
&lt;li&gt;&lt;code&gt;(?:^|\A|\G)(?:\s*(?&amp;lt;key&amp;gt;.+?)\s*:\s*(?&amp;lt;value&amp;gt;.+?)\s*)(?:\/|$)&lt;/code&gt; : add names&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The final regex actually works for the new test string with the extra colon in it since the non-greedy indicator (the &lt;code&gt;?&lt;/code&gt;in &lt;code&gt;(.+?)&lt;/code&gt;) will stop at the first &lt;code&gt;:&lt;/code&gt; match.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;parse_regex&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; inputString:&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;) &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; -&amp;gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;Dictionary&lt;/span&gt;&amp;lt;&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;,&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;&amp;gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;pattern&lt;/span&gt; = &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;/&lt;/span&gt;(?:&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;^|&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;\&lt;/span&gt;A&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;|&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;\&lt;/span&gt;G)(?:&lt;span style=&#34;color:#ed8796&#34;&gt;\&lt;/span&gt;s&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;*&lt;/span&gt;(?&amp;lt;key&amp;gt;.&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;+?&lt;/span&gt;)&lt;span style=&#34;color:#ed8796&#34;&gt;\&lt;/span&gt;s&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;*&lt;/span&gt;:&lt;span style=&#34;color:#ed8796&#34;&gt;\&lt;/span&gt;s&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;*&lt;/span&gt;(?&amp;lt;value&amp;gt;.&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;+?&lt;/span&gt;)&lt;span style=&#34;color:#ed8796&#34;&gt;\&lt;/span&gt;s&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;*&lt;/span&gt;)(?:&lt;span style=&#34;color:#ed8796&#34;&gt;\&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;/|&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;$&lt;/span&gt;)&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;/&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;dictionary&lt;/span&gt;:&lt;span style=&#34;color:#91d7e3&#34;&gt;Dictionary&lt;/span&gt;&amp;lt;&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;, &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;&amp;gt; = [:]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;matches&lt;/span&gt; = inputString.matches(of: pattern)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;for&lt;/span&gt; match &lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt; matches {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        dictionary[&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;(match.output.key)] = &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;(match.output.value)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; dictionary
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ul&gt;
&lt;li&gt;NOTE: to get this to run in a Swift Package (swift-tools-version: 5.10) with the /regex/ notation add the following to the &lt;code&gt;Package.swift&lt;/code&gt; file.&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;swiftSettings&lt;/span&gt;: [SwiftSetting] = [
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    .enableUpcomingFeature(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;BareSlashRegexLiterals&amp;#34;&lt;/span&gt;),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;for&lt;/span&gt; target &lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt; package.targets {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    target.swiftSettings = target.swiftSettings ?? []
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    target.swiftSettings?.append(contentsOf: swiftSettings)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The same regex done with the RegEx Builder would look something like (&lt;a href=&#34;https://paiv.github.io/swift-rxbgen/&#34;&gt;generator&lt;/a&gt; to get started):&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;parse_regexLong&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; inputString:&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;) -&amp;gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;Dictionary&lt;/span&gt;&amp;lt;&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;,&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;&amp;gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;key&lt;/span&gt; = Reference(Substring.&lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;value&lt;/span&gt; = Reference(Substring.&lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;pattern&lt;/span&gt; = Regex {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        ChoiceOf {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            Anchor.startOfLine &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//^&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            Anchor.startOfSubject &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//A&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            Anchor.firstMatchingPositionInSubject &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//G&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        Regex {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            ZeroOrMore { CharacterClass.whitespace }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            Capture(&lt;span style=&#34;color:#c6a0f6&#34;&gt;as&lt;/span&gt;: key) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                OneOrMore(.reluctant) { CharacterClass.any }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            ZeroOrMore { CharacterClass.whitespace }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;:&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            ZeroOrMore { CharacterClass.whitespace }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            Capture(&lt;span style=&#34;color:#c6a0f6&#34;&gt;as&lt;/span&gt;: value) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                OneOrMore(.reluctant) { CharacterClass.any }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            ZeroOrMore { CharacterClass.whitespace }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        ChoiceOf {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;/&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            Anchor.endOfLine
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;dictionary&lt;/span&gt;:&lt;span style=&#34;color:#91d7e3&#34;&gt;Dictionary&lt;/span&gt;&amp;lt;&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;, &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;&amp;gt; = [:]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;matches&lt;/span&gt; = inputString.matches(of: pattern)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;for&lt;/span&gt; match &lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt; matches {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        dictionary[&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;(match[key])] = &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;(match[value])
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; dictionary
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;One can use bare slash syntax in the builder!&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;pattern&lt;/span&gt; = Regex {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;/&lt;/span&gt;(?:&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;^|&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;\&lt;/span&gt;A&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;|&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;\&lt;/span&gt;G)&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;/&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;/&lt;/span&gt;(?:&lt;span style=&#34;color:#ed8796&#34;&gt;\&lt;/span&gt;s&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;*&lt;/span&gt;(.&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;+?&lt;/span&gt;)&lt;span style=&#34;color:#ed8796&#34;&gt;\&lt;/span&gt;s&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;*&lt;/span&gt;:&lt;span style=&#34;color:#ed8796&#34;&gt;\&lt;/span&gt;s&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;*&lt;/span&gt;(.&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;+?&lt;/span&gt;)&lt;span style=&#34;color:#ed8796&#34;&gt;\&lt;/span&gt;s&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;*&lt;/span&gt;)&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;/&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;/&lt;/span&gt;(?:&lt;span style=&#34;color:#ed8796&#34;&gt;\&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;/|&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;$&lt;/span&gt;)&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;/&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Do watch the &lt;a href=&#34;https://developer.apple.com/wwdc22/110357&#34;&gt;WWDC22 Meet RegEx talk&lt;/a&gt;. It&amp;rsquo;s hilarious and informative.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://developer.apple.com/documentation/swift/regex&#34;&gt;https://developer.apple.com/documentation/swift/regex&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://www.hackingwithswift.com/swift/5.7/regexes&#34;&gt;https://www.hackingwithswift.com/swift/5.7/regexes&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://developer.apple.com/wwdc22/110358&#34;&gt;https://developer.apple.com/wwdc22/110358&lt;/a&gt; (the beyond the basics one)&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/val-verde/swift-experimental-string-processing/blob/49418d2db5d58822db0149c03e78013183c45eeb/Sources/_MatchingEngine/Regex/AST/Atom.swift#L220&#34;&gt;https://github.com/val-verde/swift-experimental-string-processing/blob/49418d2db5d58822db0149c03e78013183c45eeb/Sources/_MatchingEngine/Regex/AST/Atom.swift#L220&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;scanner-example&#34;&gt;Scanner example&lt;/h2&gt;
&lt;p&gt;A number of examples use the built in &lt;a href=&#34;https://developer.apple.com/documentation/foundation/scanner/&#34;&gt;Scanner&lt;/a&gt; class. &lt;code&gt;Scanner&lt;/code&gt; works like an Encoder in that you give the &lt;code&gt;Scanner&lt;/code&gt; the string to analyze and it holds it in its own memory.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://developer.apple.com/documentation/foundation/scanner&#34;&gt;https://developer.apple.com/documentation/foundation/scanner&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://www.swiftbysundell.com/articles/string-parsing-in-swift/&#34;&gt;https://www.swiftbysundell.com/articles/string-parsing-in-swift/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://nshipster.com/nsscanner/&#34;&gt;https://nshipster.com/nsscanner/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://talk.objc.io/episodes/S01E13-parsing-techniques&#34;&gt;https://talk.objc.io/episodes/S01E13-parsing-techniques&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;parse_scanner&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; inputString:&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;) &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; -&amp;gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;Dictionary&lt;/span&gt;&amp;lt;&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;,&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;&amp;gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;scanner&lt;/span&gt; = Scanner(string: inputString)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;dictionary&lt;/span&gt;:&lt;span style=&#34;color:#91d7e3&#34;&gt;Dictionary&lt;/span&gt;&amp;lt;&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;,&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;&amp;gt; = [:]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;while&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;!&lt;/span&gt;scanner.isAtEnd {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;key&lt;/span&gt; = scanner.scanUpToString(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;:&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        key = key?.trimmingCharacters(&lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt;: .whitespacesAndNewlines)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;_&lt;/span&gt;  = scanner.scanCharacter()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;value&lt;/span&gt; = scanner.scanUpToString(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;/&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        value = value?.trimmingCharacters(&lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt;: .whitespacesAndNewlines)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;_&lt;/span&gt;  = scanner.scanCharacter()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;key&lt;/span&gt;, &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;value&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            dictionary[key] = value
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        } &lt;span style=&#34;color:#c6a0f6&#34;&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;throw&lt;/span&gt; HousePlantError.notAKeyValuePair
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; dictionary
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Notice I&amp;rsquo;m still trimming the whitespace. The default &lt;a href=&#34;https://developer.apple.com/documentation/foundation/scanner/1410204-characterstobeskipped&#34;&gt;&lt;code&gt;charactersToBeSkipped&lt;/code&gt;&lt;/a&gt; settings of the scanner will make the Scanner ignore any whitespace outside of a scan. For this string that means it will skip any &amp;ldquo;leading&amp;rdquo; white space for our keys and values (at the start of the string, immediately after the &amp;ldquo;:&amp;rdquo; or immediately after &amp;ldquo;/&amp;rdquo;). Once the scanner considers itself mid-scan it will no longer ignore the characters (&lt;a href=&#34;https://stackoverflow.com/questions/63546740/how-does-swifts-scanner-characterstobeskipped-work&#34;&gt;discussion&lt;/a&gt;). That leaves all the trailing whitespace to lop off (and no &lt;code&gt;.trimSuffix&lt;/code&gt; to do it).&lt;/p&gt;
&lt;p&gt;Another Scanner example, this time adding the delimiters to the skipped characters:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;parse_scanner2&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; inputString:&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;) &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; -&amp;gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;Dictionary&lt;/span&gt;&amp;lt;&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;,&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;&amp;gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;dictionary&lt;/span&gt;:&lt;span style=&#34;color:#91d7e3&#34;&gt;Dictionary&lt;/span&gt;&amp;lt;&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;,&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;&amp;gt; = [:]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;itemDelimiter&lt;/span&gt; = CharacterSet(charactersIn: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;/&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;keyValueDelimiter&lt;/span&gt; = CharacterSet(charactersIn: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;:&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;kvDelimAndWhite&lt;/span&gt; = CharacterSet()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        .union(keyValueDelimiter)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        .union(.whitespacesAndNewlines)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;allDelimAndWhite&lt;/span&gt; = CharacterSet()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        .union(itemDelimiter)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        .union(keyValueDelimiter)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        .union(.whitespacesAndNewlines)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;scanner&lt;/span&gt; = Scanner(string: inputString)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    scanner.charactersToBeSkipped = allDelimAndWhite
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;while&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;!&lt;/span&gt;scanner.isAtEnd {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;key&lt;/span&gt; = scanner.scanCharacters(from: kvDelimAndWhite.inverted)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;value&lt;/span&gt; = scanner.scanCharacters(from: itemDelimiter.inverted)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        value = value?.trimmingCharacters(&lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt;: .whitespacesAndNewlines)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;key&lt;/span&gt;, &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;value&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            dictionary[key] = value
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        } &lt;span style=&#34;color:#c6a0f6&#34;&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;throw&lt;/span&gt; HousePlantError.notAKeyValuePair
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; dictionary
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;In this example a key should never have whitespace so the Scanner can run through whitespace characters as part of the delimiter search. No more trimming for the key.&lt;/p&gt;
&lt;h2 id=&#34;scanner--dynamic-sequence&#34;&gt;Scanner + Dynamic Sequence&lt;/h2&gt;
&lt;p&gt;I once saw an &lt;a href=&#34;https://github.com/aflockofswifts/meetings/blob/902f6dc4c3e4564713ce5a41d74a2a275bb5883f/2022/README.md?plain=1#L373&#34;&gt;interesting demo&lt;/a&gt; of combining a Scanner with a &lt;a href=&#34;https://developer.apple.com/documentation/swift/sequence(state:next:)/&#34;&gt;Dynamic Sequence&lt;/a&gt; (&lt;a href=&#34;https://forums.swift.org/t/review-se-0094-add-sequence-initial-next-and-sequence-state-next-to-the-stdlib/&#34;&gt;SE-0094 Review Post&lt;/a&gt;), which works especially well if one had multiple items to dig through. We aren&amp;rsquo;t parsing multiple &lt;code&gt;HousePlants&lt;/code&gt; yet, so I&amp;rsquo;ll put a different example in for reference.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;numbersInString&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; input:&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;numbersInString&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;result&lt;/span&gt; = sequence(state: Scanner(string: input)) { scanner &lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;string&lt;/span&gt; = scanner.scanCharacters(from: .decimalDigits.inverted )
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(string ?? &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;none found&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; scanner.scanInt()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }.&lt;span style=&#34;color:#91d7e3&#34;&gt;map&lt;/span&gt;({ &lt;span style=&#34;color:#f4dbd6&#34;&gt;$0&lt;/span&gt; })
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(result)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;numbersInSubString&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; input:&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;numbersInSubString&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;result&lt;/span&gt; = sequence(state: Scanner(string: input)) { scanner &lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            scanner.scanUpToString(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\n&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;).&lt;span style=&#34;color:#91d7e3&#34;&gt;map&lt;/span&gt; { subString &lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(subString)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; sequence(state: Scanner(string: subString)) { subScanner &lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;string&lt;/span&gt; = subScanner.scanCharacters(from: .decimalDigits.inverted )
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    &lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(string ?? &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;none found&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; subScanner.scanInt()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                }.&lt;span style=&#34;color:#91d7e3&#34;&gt;map&lt;/span&gt;({ &lt;span style=&#34;color:#f4dbd6&#34;&gt;$0&lt;/span&gt; })
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }.&lt;span style=&#34;color:#91d7e3&#34;&gt;map&lt;/span&gt;({ &lt;span style=&#34;color:#f4dbd6&#34;&gt;$0&lt;/span&gt; })
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(result)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;testParse&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        numbersInString(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;hda23hfw78hdjila2889&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\n&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;hda7991hfw12hdjila9&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\n&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;hufie281sufvns0938dhqqj8837&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//[23, 78, 2889, 7991, 12, 9, 281, 938, 8837]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        numbersInSubString(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;hda23hfw78hdjila2889&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\n&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;hda7991hfw12hdjila9&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\n&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;hufie281sufvns0938dhqqj8837&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//[[23, 78, 2889], [7991, 12, 9], [281, 938, 8837]]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This style provides a chance for the Scanner to just jump to the end of the Substring when getting a value like with the String.split(&amp;quot;/&amp;quot;) examples. Apparently it still saves some time even though the key chars probably get scanned twice.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;parse_subScanner&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; inputString:&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;) &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; -&amp;gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;Dictionary&lt;/span&gt;&amp;lt;&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;,&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;&amp;gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;dictionary&lt;/span&gt;:&lt;span style=&#34;color:#91d7e3&#34;&gt;Dictionary&lt;/span&gt;&amp;lt;&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;,&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;&amp;gt; = [:]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;itemDelimiter&lt;/span&gt; = CharacterSet(charactersIn: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;/&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;keyValueDelimiter&lt;/span&gt; = CharacterSet(charactersIn: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;:&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;kvDelimAndWhite&lt;/span&gt; = CharacterSet()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        .union(keyValueDelimiter)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        .union(.whitespacesAndNewlines)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;allDelimAndWhite&lt;/span&gt; = CharacterSet()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        .union(itemDelimiter)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        .union(keyValueDelimiter)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        .union(.whitespacesAndNewlines)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;topScanner&lt;/span&gt; = Scanner(string: inputString)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    topScanner.charactersToBeSkipped = allDelimAndWhite
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    sequence(state: topScanner) { topScanner &lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        topScanner.scanCharacters(from: itemDelimiter.inverted).&lt;span style=&#34;color:#91d7e3&#34;&gt;map&lt;/span&gt; { subString &lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;subScanner&lt;/span&gt; = Scanner(string: subString)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            subScanner.charactersToBeSkipped = allDelimAndWhite
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;key&lt;/span&gt; = subScanner.scanCharacters(from: kvDelimAndWhite.inverted)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            subScanner.charactersToBeSkipped = &lt;span style=&#34;color:#f5a97f&#34;&gt;nil&lt;/span&gt; &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//turn off skipping!! &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;_&lt;/span&gt; = subScanner.scanCharacters(from: kvDelimAndWhite)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;startValue&lt;/span&gt;:&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;.Index = subScanner.currentIndex
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;value&lt;/span&gt;:&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;? = subScanner.string.substring(from: startValue)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;key&lt;/span&gt;, &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;value&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                dictionary[key] = value
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }.&lt;span style=&#34;color:#91d7e3&#34;&gt;map&lt;/span&gt;({ &lt;span style=&#34;color:#f4dbd6&#34;&gt;$0&lt;/span&gt; })
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; dictionary
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;hand-coded-scanner&#34;&gt;Hand coded scanner&lt;/h2&gt;
&lt;p&gt;Last example, walking through a String, char by char, appending to the dictionary as we go.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://www.objc.io/blog/2019/02/05/a-scanner-alternative/&#34;&gt;https://www.objc.io/blog/2019/02/05/a-scanner-alternative/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://talk.objc.io/episodes/S01E79-string-parsing-performance&#34;&gt;https://talk.objc.io/episodes/S01E79-string-parsing-performance&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://gist.github.com/milseman/f9b5528345db3a36bbdd138af52c5cda&#34;&gt;https://gist.github.com/milseman/f9b5528345db3a36bbdd138af52c5cda&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;parse_charScanner&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; inputString:&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;) -&amp;gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;Dictionary&lt;/span&gt;&amp;lt;&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;,&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;&amp;gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;result&lt;/span&gt;: &lt;span style=&#34;color:#91d7e3&#34;&gt;Dictionary&lt;/span&gt;&amp;lt;&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;,&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;&amp;gt; = [:]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;isKey&lt;/span&gt; = &lt;span style=&#34;color:#f5a97f&#34;&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;currentKey&lt;/span&gt; = &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;.unicodeScalars
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;currentValue&lt;/span&gt; = &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;.unicodeScalars
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        @inline(__always) &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;add&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;key&lt;/span&gt; = &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;(currentKey).trimmingCharacters(&lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt;: .whitespacesAndNewlines)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;value&lt;/span&gt; = &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;(currentValue).trimmingCharacters(&lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt;: .whitespacesAndNewlines)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            result[key] = value
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        @inline(__always) &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;flush&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            currentKey.&lt;span style=&#34;color:#91d7e3&#34;&gt;removeAll&lt;/span&gt;()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            currentValue.&lt;span style=&#34;color:#91d7e3&#34;&gt;removeAll&lt;/span&gt;()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            isKey = &lt;span style=&#34;color:#f5a97f&#34;&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;for&lt;/span&gt; c &lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt; inputString.unicodeScalars {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; isKey {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#c6a0f6&#34;&gt;switch&lt;/span&gt; c {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#c6a0f6&#34;&gt;case&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;:&amp;#34;&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    isKey = &lt;span style=&#34;color:#f5a97f&#34;&gt;false&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#c6a0f6&#34;&gt;default&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    currentKey.append(c)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            } &lt;span style=&#34;color:#c6a0f6&#34;&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#c6a0f6&#34;&gt;switch&lt;/span&gt; c {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#c6a0f6&#34;&gt;case&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;/&amp;#34;&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    add()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    flush()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#c6a0f6&#34;&gt;default&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    currentValue.append(c)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        add()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; result
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;I did try a few different variations, including using &lt;code&gt;UnsafeBytes&lt;/code&gt; and everything seemed slower or on par with this one.&lt;/p&gt;
&lt;h2 id=&#34;summary&#34;&gt;Summary&lt;/h2&gt;
&lt;p&gt;I&amp;rsquo;ve got a handful of ways to get a &lt;code&gt;Dictionary&lt;/code&gt; out of my &amp;ldquo;/:&amp;rdquo; formatted string. They do handle malformed Strings differently, but overall&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The &lt;code&gt;Scanner&lt;/code&gt; and the custom scanner are fastest.&lt;/li&gt;
&lt;li&gt;The raw string regex is the most succinct, but the slowest.&lt;/li&gt;
&lt;li&gt;The split-split with the match of one gets it done with the least rigamarole.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;None of these let me handle items that won&amp;rsquo;t be a String yet. Next post&amp;hellip; turning a &lt;code&gt;String&lt;/code&gt; into a &lt;code&gt;Date&lt;/code&gt;.&lt;/p&gt;
</description>
    </item>
    
    
    
    <item>
      <title>And what can I make a custom Encoder do?</title>
      <link>https://whynotestflight.com/excuses/and-what-can-i-make-a-custom-encoder-do/</link>
      <pubDate>Mon, 11 Mar 2024 00:00:00 +0000</pubDate>
      
      <guid>https://whynotestflight.com/excuses/and-what-can-i-make-a-custom-encoder-do/</guid>
      <description>&lt;p&gt;Relevant repo: &lt;a href=&#34;https://github.com/carlynorama/CoderExplorer/&#34;&gt;https://github.com/carlynorama/CoderExplorer/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;After &lt;a href=&#34;https://whynotestflight.com/excuses/how-do-custom-encoders-work/&#34;&gt;last post&amp;rsquo;s&lt;/a&gt; extensive review of options, I decided to write an Encoder along lines of the &lt;a href=&#34;https://stackoverflow.com/questions/45169254/custom-swift-encoder-decoder-for-the-strings-resource-format&#34;&gt;StackOverflow example&lt;/a&gt; in that&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;every item would be a &lt;code&gt;String&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;the full codingPath would be in the key.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The implementation will be different.&lt;/p&gt;
&lt;p&gt;The first test needed to pass?&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;TestStruct&lt;/span&gt;:Codable {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;number&lt;/span&gt;:&lt;span style=&#34;color:#91d7e3&#34;&gt;Int&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;text&lt;/span&gt;:&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;sub&lt;/span&gt;:TestSubStruct
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;TestSubStruct&lt;/span&gt;:Codable {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;numeral&lt;/span&gt;:&lt;span style=&#34;color:#91d7e3&#34;&gt;Int&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;string&lt;/span&gt;:&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;testExample&lt;/span&gt;() &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;encoder&lt;/span&gt; = SimpleCoder()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;sub&lt;/span&gt; = TestSubStruct(numeral: &lt;span style=&#34;color:#f5a97f&#34;&gt;34&lt;/span&gt;, string: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;world&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;testItem&lt;/span&gt; = TestStruct(number: &lt;span style=&#34;color:#f5a97f&#34;&gt;12&lt;/span&gt;, text: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;hello&amp;#34;&lt;/span&gt;, sub: sub)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;expected&lt;/span&gt; = &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;number:12/sub.numeral:34/sub.string:world/text:hello&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    XCTAssertEqual(expected, &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; encoder.encode(testItem))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ul&gt;
&lt;li&gt;&amp;ldquo;:&amp;rdquo; The delimiter between key and value&lt;/li&gt;
&lt;li&gt;&amp;ldquo;/&amp;rdquo; The delimiter between items&lt;/li&gt;
&lt;li&gt;&amp;ldquo;.&amp;rdquo; The delimiter between keys in nested values&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;getting-started-with-a-keyed-container&#34;&gt;Getting Started with a Keyed Container&lt;/h2&gt;
&lt;p&gt;Some initial decisions&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Since not a lot of fancy is going to be happening, all of the smarts should live in the &lt;code&gt;:Encoder&lt;/code&gt; so I don&amp;rsquo;t have to go chasing around the whole code base to find it.&lt;/li&gt;
&lt;li&gt;I&amp;rsquo;ll avoid doing the nested-push-pop custom codingPath data type thing for now, I&amp;rsquo;ll just make new encoders. This should cause zero problems for this &lt;code&gt;Encoder&lt;/code&gt; because every single key has its full path. We can just keep passing in the same data storage reference with no collisions or confusions.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Super basic public face of the Encoder system:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;SimpleCoder&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;encode&lt;/span&gt;&amp;lt;E:Encodable&amp;gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; value: E) &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; -&amp;gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;encoder&lt;/span&gt; = _SimpleEncoder()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; value.encode(to: encoder)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; encoder.value
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;A Dumb-As-Rocks reference type for the data, a la the &lt;a href=&#34;https://talk.objc.io/episodes/S01E348-routing-with-codable-encoding&#34;&gt;objc.io example&lt;/a&gt;&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;final&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;SimpleCoderData&lt;/span&gt;&amp;lt;Value&amp;gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;storage&lt;/span&gt;:Value
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;init&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; value: Value) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;.storage = value
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The type that will eventually conform to &lt;code&gt;Encoder&lt;/code&gt;. It will know how to turn the &lt;code&gt;SimpleCoderData&lt;/code&gt; type into a &lt;code&gt;String&lt;/code&gt;.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-Swift&#34; data-lang=&#34;Swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;_SimpleEncoder&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;data&lt;/span&gt;:SimpleCoderData&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;lt;&lt;/span&gt;[&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;: &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;]&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;codingPath&lt;/span&gt;: [CodingKey] = []
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//note: having lots of complicated work in a var&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//isn&amp;#39;t the best. I&amp;#39;m following the API of an :Encoder&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//that didn&amp;#39;t need to do any work to get its .value.  &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;value&lt;/span&gt;:&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;lines&lt;/span&gt; = data.storage.&lt;span style=&#34;color:#91d7e3&#34;&gt;map&lt;/span&gt; { key, value &lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; key.&lt;span style=&#34;color:#91d7e3&#34;&gt;isEmpty&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;||&lt;/span&gt; key.&lt;span style=&#34;color:#91d7e3&#34;&gt;contains&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;keyless&amp;#34;&lt;/span&gt;){
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;value&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            } &lt;span style=&#34;color:#c6a0f6&#34;&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;key&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;value&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//To get a consistent order out since this isn&amp;#39;t a &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//sorted dictionary. Better for testing. &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        lines.&lt;span style=&#34;color:#91d7e3&#34;&gt;sort&lt;/span&gt;()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; lines.joined(separator: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;/&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;extension&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;_SimpleEncoder&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;init&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;.data = SimpleCoderData([:])
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ul&gt;
&lt;li&gt;SIDEBAR: discussion on &lt;a href=&#34;https://forums.swift.org/t/ordereddictionary-decoding/66829&#34;&gt;Codable and value order re: OrderedDictionary&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The &lt;code&gt;_SimpleEncoder&lt;/code&gt; will also own adding values to the data var. EVERYTHING will need to have a key in this example so we only need one function that takes a non-optional &lt;code&gt;CodingKey&lt;/code&gt;.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;extension&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;_SimpleEncoder&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;encodeKey&lt;/span&gt;(key:CodingKey) -&amp;gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        (codingPath &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;+&lt;/span&gt; [key]).&lt;span style=&#34;color:#91d7e3&#34;&gt;map&lt;/span&gt; { &lt;span style=&#34;color:#f4dbd6&#34;&gt;$0&lt;/span&gt;.stringValue }.joined(separator: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;.&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//to be called from containers&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;encode&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; value: &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;, forKey key:CodingKey) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        data.storage[encodeKey(key: key)] = value
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Also in &lt;code&gt;_SimpleEncoder&lt;/code&gt;, the converters for the basic types that the Encoding Containers will use. I&amp;rsquo;m going to follow the model of them all being called the same thing, but taking different value types in as parameters.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;extension&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;_SimpleEncoder&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//called from the containers&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    @inline(__always)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;convert&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; value: some BinaryFloatingPoint) -&amp;gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#91d7e3&#34;&gt;Double&lt;/span&gt;(value).description
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    @inline(__always)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;convert&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; value: some FixedWidthInteger) &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; -&amp;gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;guard&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;validatedValue&lt;/span&gt; = &lt;span style=&#34;color:#91d7e3&#34;&gt;Int&lt;/span&gt;(exactly: value) &lt;span style=&#34;color:#c6a0f6&#34;&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;throw&lt;/span&gt; EncodingError.invalidValue(value, EncodingError.Context(codingPath: codingPath, debugDescription: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Integer out of range.&amp;#34;&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; validatedValue.description
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now for the actual conformance - time to make up some names for the encoding containers.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;extension&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;_SimpleEncoder&lt;/span&gt;:Encoder {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;userInfo&lt;/span&gt;: [CodingUserInfoKey : &lt;span style=&#34;color:#91d7e3&#34;&gt;Any&lt;/span&gt;] { [:] }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;container&lt;/span&gt;&amp;lt;Key&amp;gt;(keyedBy type: Key.&lt;span style=&#34;color:#c6a0f6&#34;&gt;Type&lt;/span&gt;) -&amp;gt; KeyedEncodingContainer&amp;lt;Key&amp;gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;where&lt;/span&gt; Key : CodingKey {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        KeyedEncodingContainer(SimpleEncoderKEC&amp;lt;Key&amp;gt;(encoder: &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;unkeyedContainer&lt;/span&gt;() -&amp;gt; UnkeyedEncodingContainer {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#91d7e3&#34;&gt;fatalError&lt;/span&gt;()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//SimpleCoderUEC(encoder: self)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;singleValueContainer&lt;/span&gt;() -&amp;gt; SingleValueEncodingContainer {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#91d7e3&#34;&gt;fatalError&lt;/span&gt;()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;       &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//SimpleCoderSVEC(encoder: self)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;the-keyedencodingcontainer&#34;&gt;The KeyedEncodingContainer&lt;/h2&gt;
&lt;p&gt;I followed the pattern from the &lt;a href=&#34;https://github.com/apple/swift-openapi-runtime/tree/release/0.2.x/Sources/OpenAPIRuntime/URICoder&#34;&gt;&lt;code&gt;URIEncoder&lt;/code&gt;&lt;/a&gt; for my encoding containers, with the wrinkle that everything has to get a key. That&amp;rsquo;s not hard to envision with the KeyedContainer. We&amp;rsquo;ll get the first test case to pass by just implementing this one.&lt;/p&gt;
&lt;h3 id=&#34;the-init&#34;&gt;The init&lt;/h3&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;SimpleEncoderKEC&lt;/span&gt;&amp;lt;Key: CodingKey&amp;gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;encoder&lt;/span&gt;: _SimpleEncoder
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;the-custom-functions&#34;&gt;The custom functions&lt;/h3&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;extension&lt;/span&gt;  &lt;span style=&#34;color:#eed49f&#34;&gt;SimpleEncoderKEC&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;private&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;_insertValue&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; converted:&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;, atKey key: Key) &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; encoder.encode(converted, forKey: key)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;private&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;_insertBinaryFloatingPoint&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; value: some BinaryFloatingPoint, atKey key: Key) &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; _insertValue(encoder.convert(value), atKey: key)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;private&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;_insertFixedWidthInteger&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; value: some FixedWidthInteger, atKey key: Key) &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; _insertValue(encoder.convert(value), atKey: key)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;the-conformance&#34;&gt;The conformance&lt;/h3&gt;
&lt;p&gt;Full disclosure, I did not write tests for all of the &lt;code&gt;func encode()&lt;/code&gt; functions that I yanked from the &lt;a href=&#34;https://github.com/apple/swift-openapi-runtime/tree/release/0.2.x/Sources/OpenAPIRuntime/URICoder&#34;&gt;&lt;code&gt;URIEncoder&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;extension&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;SimpleEncoderKEC&lt;/span&gt;:KeyedEncodingContainerProtocol {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;codingPath&lt;/span&gt;: [CodingKey] {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        encoder.codingPath
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;mutating&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;encodeNil&lt;/span&gt;(forKey key: Key) &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;TODO:&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt; Decide about nils&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#91d7e3&#34;&gt;fatalError&lt;/span&gt;()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;mutating&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;encode&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; value: &lt;span style=&#34;color:#91d7e3&#34;&gt;Bool&lt;/span&gt;, forKey key: Key) &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; { &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; _insertValue(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;value&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;, atKey: key) }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;mutating&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;encode&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; value: &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;, forKey key: Key) &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; { &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; _insertValue(value, atKey: key) }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;mutating&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;encode&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; value: &lt;span style=&#34;color:#91d7e3&#34;&gt;Double&lt;/span&gt;, forKey key: Key) &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; { &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; _insertBinaryFloatingPoint(value, atKey: key) }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;mutating&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;encode&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; value: &lt;span style=&#34;color:#91d7e3&#34;&gt;Float&lt;/span&gt;, forKey key: Key) &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; { &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; _insertBinaryFloatingPoint(value, atKey: key) }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;mutating&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;encode&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; value: &lt;span style=&#34;color:#91d7e3&#34;&gt;Int&lt;/span&gt;, forKey key: Key) &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; { &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; _insertFixedWidthInteger(value, atKey: key) }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;mutating&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;encode&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; value: &lt;span style=&#34;color:#91d7e3&#34;&gt;Int8&lt;/span&gt;, forKey key: Key) &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; { &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; _insertFixedWidthInteger(value, atKey: key) }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;mutating&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;encode&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; value: &lt;span style=&#34;color:#91d7e3&#34;&gt;Int16&lt;/span&gt;, forKey key: Key) &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; { &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; _insertFixedWidthInteger(value, atKey: key) }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;mutating&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;encode&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; value: &lt;span style=&#34;color:#91d7e3&#34;&gt;Int32&lt;/span&gt;, forKey key: Key) &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; { &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; _insertFixedWidthInteger(value, atKey: key) }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;mutating&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;encode&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; value: &lt;span style=&#34;color:#91d7e3&#34;&gt;Int64&lt;/span&gt;, forKey key: Key) &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; { &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; _insertFixedWidthInteger(value, atKey: key) }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;mutating&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;encode&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; value: &lt;span style=&#34;color:#91d7e3&#34;&gt;UInt&lt;/span&gt;, forKey key: Key) &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; { &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; _insertFixedWidthInteger(value, atKey: key) }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;mutating&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;encode&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; value: &lt;span style=&#34;color:#91d7e3&#34;&gt;UInt8&lt;/span&gt;, forKey key: Key) &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; { &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; _insertFixedWidthInteger(value, atKey: key) }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;mutating&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;encode&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; value: &lt;span style=&#34;color:#91d7e3&#34;&gt;UInt16&lt;/span&gt;, forKey key: Key) &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; { &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; _insertFixedWidthInteger(value, atKey: key) }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;mutating&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;encode&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; value: &lt;span style=&#34;color:#91d7e3&#34;&gt;UInt32&lt;/span&gt;, forKey key: Key) &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; { &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; _insertFixedWidthInteger(value, atKey: key) }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;mutating&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;encode&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; value: &lt;span style=&#34;color:#91d7e3&#34;&gt;UInt64&lt;/span&gt;, forKey key: Key) &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; { &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; _insertFixedWidthInteger(value, atKey: key) }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;mutating&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;encode&lt;/span&gt;&amp;lt;T&amp;gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; value: T, forKey key: Key) &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;where&lt;/span&gt; T: Encodable {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//notice the reference to the existing data! &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//not using push and pop style like URIEncoder.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;tmpEncoder&lt;/span&gt; = _SimpleEncoder(data: encoder.data)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        tmpEncoder.codingPath.append(key)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; value.encode(to: tmpEncoder)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;mutating&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;nestedContainer&lt;/span&gt;&amp;lt;NestedKey&amp;gt;(keyedBy keyType: NestedKey.&lt;span style=&#34;color:#c6a0f6&#34;&gt;Type&lt;/span&gt;, forKey key: Key)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        -&amp;gt; KeyedEncodingContainer&amp;lt;NestedKey&amp;gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;where&lt;/span&gt; NestedKey: CodingKey
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    { &lt;span style=&#34;color:#91d7e3&#34;&gt;fatalError&lt;/span&gt;() }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;mutating&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;nestedUnkeyedContainer&lt;/span&gt;(forKey key: Key) -&amp;gt; any UnkeyedEncodingContainer { &lt;span style=&#34;color:#91d7e3&#34;&gt;fatalError&lt;/span&gt;() }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;mutating&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;superEncoder&lt;/span&gt;() -&amp;gt; any Encoder { &lt;span style=&#34;color:#91d7e3&#34;&gt;fatalError&lt;/span&gt;() }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;mutating&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;superEncoder&lt;/span&gt;(forKey key: Key) -&amp;gt; any Encoder { &lt;span style=&#34;color:#91d7e3&#34;&gt;fatalError&lt;/span&gt;() }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;I&amp;rsquo;m super generous with the fatal errors at this point because I&amp;rsquo;ll go back in and fix them as they fire.&lt;/p&gt;
&lt;p&gt;And this passes the first test!&lt;/p&gt;
&lt;h2 id=&#34;unkeyedcontainer&#34;&gt;UnkeyedContainer&lt;/h2&gt;
&lt;h3 id=&#34;the-test&#34;&gt;The test&lt;/h3&gt;
&lt;p&gt;Let&amp;rsquo;s try this test that has Arrays in it.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;MoreItems&lt;/span&gt;:Codable {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;myDouble&lt;/span&gt;:&lt;span style=&#34;color:#91d7e3&#34;&gt;Double&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;myFloat&lt;/span&gt;:&lt;span style=&#34;color:#91d7e3&#34;&gt;Float&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;myArray&lt;/span&gt;:[InsideStruct]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;InsideStruct&lt;/span&gt;:Codable {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;insideDouble&lt;/span&gt;:&lt;span style=&#34;color:#91d7e3&#34;&gt;Double&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;insideFloat&lt;/span&gt;:&lt;span style=&#34;color:#91d7e3&#34;&gt;Float&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//let insideArray:[TestSubStruct]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;testArrayExample&lt;/span&gt;() &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;encoder&lt;/span&gt; = SimpleCoder()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;subItem1&lt;/span&gt; = InsideStruct(insideDouble: &lt;span style=&#34;color:#f5a97f&#34;&gt;0.234&lt;/span&gt;, insideFloat: &lt;span style=&#34;color:#f5a97f&#34;&gt;2144.421&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;subItem2&lt;/span&gt; = InsideStruct(insideDouble: &lt;span style=&#34;color:#f5a97f&#34;&gt;5.926&lt;/span&gt;, insideFloat: &lt;span style=&#34;color:#f5a97f&#34;&gt;0.00132&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;subItem3&lt;/span&gt; = InsideStruct(insideDouble: &lt;span style=&#34;color:#f5a97f&#34;&gt;312421.4124214&lt;/span&gt;, insideFloat: &lt;span style=&#34;color:#f5a97f&#34;&gt;421421.223&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;testItem&lt;/span&gt; = MoreItems(myDouble: &lt;span style=&#34;color:#f5a97f&#34;&gt;8921.41421&lt;/span&gt;, myFloat: &lt;span style=&#34;color:#f5a97f&#34;&gt;1182.12&lt;/span&gt;, myArray: [subItem1, subItem2, subItem3])
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;expected&lt;/span&gt; =  &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;myArray.0.insideDouble:0.234/&amp;#34;&lt;/span&gt;  &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;+&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;myArray.0.insideFloat:2144.4208984375/&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;+&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;myArray.1.insideDouble:5.926/&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;+&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;myArray.1.insideFloat:0.0013200000394135714/&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;+&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;myArray.2.insideDouble:312421.4124214/&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;+&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;myArray.2.insideFloat:421421.21875/&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;+&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;myDouble:8921.41421/&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;+&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;myFloat:1182.1199951171875&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    XCTAssertEqual(expected, &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; encoder.encode(testItem))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;the-init-1&#34;&gt;The init&lt;/h3&gt;
&lt;p&gt;Start off with the basic needs&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;SimpleCoderUEC&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;/// The associated encoder.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;encoder&lt;/span&gt;: _SimpleEncoder
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;private&lt;/span&gt;(&lt;span style=&#34;color:#c6a0f6&#34;&gt;set&lt;/span&gt;) &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;count&lt;/span&gt;: &lt;span style=&#34;color:#91d7e3&#34;&gt;Int&lt;/span&gt; = &lt;span style=&#34;color:#f5a97f&#34;&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;the-custom-functions-1&#34;&gt;The custom functions&lt;/h3&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;extension&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;SimpleCoderUEC&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;private&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;mutating&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;_appendValue&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; converted:&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;) &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; encoder.encode(converted, forKey: nextIndexedKey())
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;private&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;mutating&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;_appendBinaryFloatingPoint&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; value: some BinaryFloatingPoint) &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; _appendValue(encoder.convert(value))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;private&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;mutating&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;_appendFixedWidthInteger&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; value: some FixedWidthInteger) &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; _appendValue(encoder.convert(value))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;key-creation&#34;&gt;Key creation&lt;/h3&gt;
&lt;p&gt;Add what&amp;rsquo;s needed for index based keys.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;extension&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;SimpleCoderUEC&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//Require a key&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;private&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;mutating&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;nextIndexedKey&lt;/span&gt;() -&amp;gt; CodingKey {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;nextCodingKey&lt;/span&gt; = IndexedCodingKey(intValue: &lt;span style=&#34;color:#91d7e3&#34;&gt;count&lt;/span&gt;)&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;!&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#91d7e3&#34;&gt;count&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;+=&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; nextCodingKey
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;private&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;IndexedCodingKey&lt;/span&gt;: CodingKey {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;intValue&lt;/span&gt;: &lt;span style=&#34;color:#91d7e3&#34;&gt;Int&lt;/span&gt;?
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;stringValue&lt;/span&gt;: &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;init&lt;/span&gt;?(intValue: &lt;span style=&#34;color:#91d7e3&#34;&gt;Int&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;.intValue = intValue
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;.stringValue = intValue.description
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;init&lt;/span&gt;?(stringValue: &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;nil&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;the-conformance-1&#34;&gt;The conformance&lt;/h3&gt;
&lt;p&gt;Heavy on the fatal errors again.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;extension&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;SimpleCoderUEC&lt;/span&gt;: UnkeyedEncodingContainer {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;codingPath&lt;/span&gt;: [any CodingKey] { encoder.codingPath }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;nestedUnkeyedContainer&lt;/span&gt;() -&amp;gt; any UnkeyedEncodingContainer { &lt;span style=&#34;color:#91d7e3&#34;&gt;fatalError&lt;/span&gt;() }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;mutating&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;nestedContainer&lt;/span&gt;&amp;lt;NestedKey&amp;gt;(keyedBy keyType: NestedKey.&lt;span style=&#34;color:#c6a0f6&#34;&gt;Type&lt;/span&gt;) -&amp;gt; KeyedEncodingContainer&amp;lt;NestedKey&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;where&lt;/span&gt; NestedKey: CodingKey {  &lt;span style=&#34;color:#91d7e3&#34;&gt;fatalError&lt;/span&gt;()   }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;mutating&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;superEncoder&lt;/span&gt;() -&amp;gt; any Encoder { &lt;span style=&#34;color:#91d7e3&#34;&gt;fatalError&lt;/span&gt;() }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;mutating&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;encodeNil&lt;/span&gt;() &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; { &lt;span style=&#34;color:#91d7e3&#34;&gt;fatalError&lt;/span&gt;() }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;     
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;mutating&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;encode&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; value: &lt;span style=&#34;color:#91d7e3&#34;&gt;Bool&lt;/span&gt;) &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; { &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; _appendValue(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;value&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;) }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;mutating&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;encode&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; value: &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;) &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; { &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; _appendValue(value) }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;mutating&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;encode&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; value: &lt;span style=&#34;color:#91d7e3&#34;&gt;Double&lt;/span&gt;) &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; { &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; _appendBinaryFloatingPoint(value) }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;mutating&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;encode&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; value: &lt;span style=&#34;color:#91d7e3&#34;&gt;Float&lt;/span&gt;) &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; { &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; _appendBinaryFloatingPoint(value) }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;mutating&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;encode&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; value: &lt;span style=&#34;color:#91d7e3&#34;&gt;Int&lt;/span&gt;) &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; { &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; _appendFixedWidthInteger(value) }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;mutating&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;encode&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; value: &lt;span style=&#34;color:#91d7e3&#34;&gt;Int8&lt;/span&gt;) &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; { &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; _appendFixedWidthInteger(value) }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;mutating&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;encode&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; value: &lt;span style=&#34;color:#91d7e3&#34;&gt;Int16&lt;/span&gt;) &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; { &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; _appendFixedWidthInteger(value) }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;mutating&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;encode&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; value: &lt;span style=&#34;color:#91d7e3&#34;&gt;Int32&lt;/span&gt;) &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; { &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; _appendFixedWidthInteger(value) }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;mutating&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;encode&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; value: &lt;span style=&#34;color:#91d7e3&#34;&gt;Int64&lt;/span&gt;) &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; { &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; _appendFixedWidthInteger(value) }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;mutating&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;encode&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; value: &lt;span style=&#34;color:#91d7e3&#34;&gt;UInt&lt;/span&gt;) &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; { &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; _appendFixedWidthInteger(value) }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;mutating&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;encode&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; value: &lt;span style=&#34;color:#91d7e3&#34;&gt;UInt8&lt;/span&gt;) &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; { &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; _appendFixedWidthInteger(value) }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;mutating&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;encode&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; value: &lt;span style=&#34;color:#91d7e3&#34;&gt;UInt16&lt;/span&gt;) &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; { &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; _appendFixedWidthInteger(value) }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;mutating&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;encode&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; value: &lt;span style=&#34;color:#91d7e3&#34;&gt;UInt32&lt;/span&gt;) &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; { &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; _appendFixedWidthInteger(value) }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;mutating&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;encode&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; value: &lt;span style=&#34;color:#91d7e3&#34;&gt;UInt64&lt;/span&gt;) &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; { &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; _appendFixedWidthInteger(value) }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;mutating&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;encode&lt;/span&gt;&amp;lt;T&amp;gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; value: T) &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;where&lt;/span&gt; T: Encodable {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//points to same data reference! &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;tmpEncoder&lt;/span&gt; = _SimpleEncoder(data:encoder.data)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        tmpEncoder.codingPath = encoder.codingPath
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        tmpEncoder.codingPath.append(nextIndexedKey())
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; value.encode(to: tmpEncoder)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And that passes the test.&lt;/p&gt;
&lt;h2 id=&#34;singlevalues&#34;&gt;SingleValues&lt;/h2&gt;
&lt;p&gt;It may seem little funny to do the &amp;ldquo;simplest&amp;rdquo; case, single values, last. In this case we need to do some thinking about how to force them to have keys when they wouldn&amp;rsquo;t normally. I&amp;rsquo;m being a bit lazy and giving everything the phrase &amp;ldquo;keyless(UUID())&amp;rdquo; as a key. Using a &lt;code&gt;UUID&lt;/code&gt; instead of the value itself means not worrying about duplicates or if the value contains the key delimiter.&lt;/p&gt;
&lt;h3 id=&#34;the-test-1&#34;&gt;The test&lt;/h3&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;testSingleValues&lt;/span&gt;() async &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;encoder&lt;/span&gt; = SimpleCoder()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;toEncodeInt&lt;/span&gt; = &lt;span style=&#34;color:#91d7e3&#34;&gt;Int&lt;/span&gt;.random(&lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt;: &lt;span style=&#34;color:#91d7e3&#34;&gt;Int&lt;/span&gt;.&lt;span style=&#34;color:#91d7e3&#34;&gt;min&lt;/span&gt;...&lt;span style=&#34;color:#91d7e3&#34;&gt;Int&lt;/span&gt;.&lt;span style=&#34;color:#91d7e3&#34;&gt;max&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;toEncodeText&lt;/span&gt; = &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;hello&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;TODO:&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt; explore strings more&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;toEncodeBool&lt;/span&gt; = &lt;span style=&#34;color:#91d7e3&#34;&gt;Bool&lt;/span&gt;.random()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;toEncodeDouble&lt;/span&gt; = &lt;span style=&#34;color:#91d7e3&#34;&gt;Double&lt;/span&gt;.random(&lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt;: &lt;span style=&#34;color:#91d7e3&#34;&gt;Double&lt;/span&gt;.leastNonzeroMagnitude...&lt;span style=&#34;color:#91d7e3&#34;&gt;Double&lt;/span&gt;.greatestFiniteMagnitude)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;toEncodeFloat&lt;/span&gt; = &lt;span style=&#34;color:#91d7e3&#34;&gt;Float&lt;/span&gt;.random(&lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt;: &lt;span style=&#34;color:#91d7e3&#34;&gt;Float&lt;/span&gt;.leastNonzeroMagnitude...&lt;span style=&#34;color:#91d7e3&#34;&gt;Float&lt;/span&gt;.greatestFiniteMagnitude)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;toEncodeInt32&lt;/span&gt; = &lt;span style=&#34;color:#91d7e3&#34;&gt;Int32&lt;/span&gt;.random(&lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt;: &lt;span style=&#34;color:#91d7e3&#34;&gt;Int32&lt;/span&gt;.&lt;span style=&#34;color:#91d7e3&#34;&gt;min&lt;/span&gt;...&lt;span style=&#34;color:#91d7e3&#34;&gt;Int32&lt;/span&gt;.&lt;span style=&#34;color:#91d7e3&#34;&gt;max&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;encodedInt&lt;/span&gt; = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; encoder.encode(toEncodeInt)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;encodedText&lt;/span&gt; = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; encoder.encode(toEncodeText)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;encodedBool&lt;/span&gt; = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; encoder.encode(toEncodeBool)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;encodedDouble&lt;/span&gt; = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; encoder.encode(toEncodeDouble)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;encodedFloat&lt;/span&gt; = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; encoder.encode(toEncodeFloat)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;encodedInt32&lt;/span&gt; = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; encoder.encode(toEncodeInt32)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    XCTAssertEqual(toEncodeInt.description, encodedInt)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    XCTAssertEqual(toEncodeText.description, encodedText)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    XCTAssertEqual(toEncodeBool.description, encodedBool)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    XCTAssertEqual(toEncodeDouble.description, encodedDouble)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    XCTAssertEqual(&lt;span style=&#34;color:#91d7e3&#34;&gt;Double&lt;/span&gt;(toEncodeFloat).description, encodedFloat)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    XCTAssertEqual(toEncodeInt32.description, encodedInt32)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;the-init-2&#34;&gt;The init&lt;/h3&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;SimpleCoderSVEC&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;encoder&lt;/span&gt;: _SimpleEncoder
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;the-custom-functions-2&#34;&gt;The custom functions&lt;/h3&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;extension&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;SimpleCoderSVEC&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;private&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;_setValue&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; converted:&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;) &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; { 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; encoder.encode(converted, forKey: SVECCodingKey(converted)) 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;private&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;_setBinaryFloatingPoint&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; value: some BinaryFloatingPoint) &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; _setValue(encoder.convert(value))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;private&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;_setFixedWidthInteger&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; value: some FixedWidthInteger) &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; _setValue(encoder.convert(value))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;key-creation-1&#34;&gt;Key creation&lt;/h3&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;extension&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;SimpleCoderSVEC&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;private&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;SVECCodingKey&lt;/span&gt;: CodingKey {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;intValue&lt;/span&gt;: &lt;span style=&#34;color:#91d7e3&#34;&gt;Int&lt;/span&gt;?
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;stringValue&lt;/span&gt;: &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;init&lt;/span&gt;?(intValue: &lt;span style=&#34;color:#91d7e3&#34;&gt;Int&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;nil&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;init&lt;/span&gt;?(stringValue: &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;.stringValue = stringValue
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;.intValue = &lt;span style=&#34;color:#f5a97f&#34;&gt;nil&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;init&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; forValue:&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;.stringValue = &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;keyless&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;UUID&lt;span style=&#34;color:#a6da95&#34;&gt;())&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;.intValue = &lt;span style=&#34;color:#f5a97f&#34;&gt;nil&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;the-conformance-2&#34;&gt;The conformance&lt;/h3&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;extension&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;SimpleCoderSVEC&lt;/span&gt;: SingleValueEncodingContainer {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;codingPath&lt;/span&gt;: [any CodingKey] { encoder.codingPath }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;encodeNil&lt;/span&gt;() &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#91d7e3&#34;&gt;fatalError&lt;/span&gt;()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;encode&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; value: &lt;span style=&#34;color:#91d7e3&#34;&gt;Bool&lt;/span&gt;) &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; { &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; _setValue(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;value&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;) }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;encode&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; value: &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;) &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; { &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; _setValue(value) }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;encode&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; value: &lt;span style=&#34;color:#91d7e3&#34;&gt;Double&lt;/span&gt;) &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; { &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; _setBinaryFloatingPoint(value) }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;encode&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; value: &lt;span style=&#34;color:#91d7e3&#34;&gt;Float&lt;/span&gt;) &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; { &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; _setBinaryFloatingPoint(value) }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;encode&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; value: &lt;span style=&#34;color:#91d7e3&#34;&gt;Int&lt;/span&gt;) &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; { &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; _setFixedWidthInteger(value) }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;encode&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; value: &lt;span style=&#34;color:#91d7e3&#34;&gt;Int8&lt;/span&gt;) &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; { &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; _setFixedWidthInteger(value) }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;encode&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; value: &lt;span style=&#34;color:#91d7e3&#34;&gt;Int16&lt;/span&gt;) &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; { &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; _setFixedWidthInteger(value) }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;encode&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; value: &lt;span style=&#34;color:#91d7e3&#34;&gt;Int32&lt;/span&gt;) &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; { &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; _setFixedWidthInteger(value) }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;encode&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; value: &lt;span style=&#34;color:#91d7e3&#34;&gt;Int64&lt;/span&gt;) &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; { &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; _setFixedWidthInteger(value) }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;encode&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; value: &lt;span style=&#34;color:#91d7e3&#34;&gt;UInt&lt;/span&gt;) &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; { &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; _setFixedWidthInteger(value) }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;encode&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; value: &lt;span style=&#34;color:#91d7e3&#34;&gt;UInt8&lt;/span&gt;) &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; { &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; _setFixedWidthInteger(value) }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;encode&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; value: &lt;span style=&#34;color:#91d7e3&#34;&gt;UInt16&lt;/span&gt;) &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; { &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; _setFixedWidthInteger(value) }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;encode&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; value: &lt;span style=&#34;color:#91d7e3&#34;&gt;UInt32&lt;/span&gt;) &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; { &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; _setFixedWidthInteger(value) }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;encode&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; value: &lt;span style=&#34;color:#91d7e3&#34;&gt;UInt64&lt;/span&gt;) &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; { &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; _setFixedWidthInteger(value) }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;encode&lt;/span&gt;&amp;lt;T&amp;gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; value: T) &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;where&lt;/span&gt; T: Encodable {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; value.encode(to: encoder)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And again the test passes!&lt;/p&gt;
&lt;h2 id=&#34;fixing-the-dates&#34;&gt;Fixing the Dates&lt;/h2&gt;
&lt;p&gt;Before going on to tackle more complicated data structures I want to sort out a few value types that don&amp;rsquo;t get encoded the way I want by default. &lt;code&gt;Date&lt;/code&gt;, &lt;code&gt;URL&lt;/code&gt; and &lt;code&gt;Data&lt;/code&gt;.  Starting with Date, this is the test to pass.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;testDate&lt;/span&gt;() &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;encoder&lt;/span&gt; = SimpleCoder()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;date&lt;/span&gt; = Date()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;dateString&lt;/span&gt; = date.ISO8601Format(.iso8601)        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;encodedDate&lt;/span&gt; = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; encoder.encode(date)       
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    XCTAssertEqual(dateString, encodedDate)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;It doesn&amp;rsquo;t out of the gate. It fails with the error:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;XCTAssertEqual failed: (&amp;#34;2024-03-07T14:55:56Z&amp;#34;) is not equal to (&amp;#34;731516156.037366&amp;#34;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The one below does though, which shows us that the default &lt;code&gt;Encoding&lt;/code&gt; for &lt;code&gt;Date&lt;/code&gt;&amp;rsquo;s &lt;code&gt;Codable&lt;/code&gt; implementation (&lt;a href=&#34;https://github.com/apple/swift-corelibs-foundation/blob/1dac1132d49b0ee4213ac89473019cae8a608b5c/Sources/Foundation/Date.swift#L284&#34;&gt;core&lt;/a&gt; | &lt;a href=&#34;https://github.com/apple/swift-foundation/blob/69a6e9f4902f5043a89fbfa1da0e89a1ffe367fe/Sources/FoundationEssentials/Date.swift#L307&#34;&gt;FoundationEssential&lt;/a&gt;) is the &lt;code&gt;timeIntervalSinceReferenceDate&lt;/code&gt;.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;testDate&lt;/span&gt;() &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;encoder&lt;/span&gt; = SimpleCoder()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;date&lt;/span&gt; = Date()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;dateString&lt;/span&gt; = &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;date.timeIntervalSinceReferenceDate&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;encodedDate&lt;/span&gt; = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; encoder.encode(date)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    XCTAssertEqual(dateString, encodedDate)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;How to fix it? First off, the encoder has to catch that a &lt;code&gt;Date&lt;/code&gt; has come into play. We&amp;rsquo;ll catch it in the &lt;code&gt;func encode&amp;lt;T&amp;gt;(_ value: T)&lt;/code&gt; functions in &lt;em&gt;all three encoding containers&lt;/em&gt; by adding a case statement to each.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;mutating&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;encode&lt;/span&gt;&amp;lt;T&amp;gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; value: T, 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                        forKey key: Key
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                       ) &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;where&lt;/span&gt; T: Encodable {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;switch&lt;/span&gt; value {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;case&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;value&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;as&lt;/span&gt; Date: &lt;span style=&#34;color:#91d7e3&#34;&gt;fatalError&lt;/span&gt;()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;default&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//points to same data reference! &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;tmpEncoder&lt;/span&gt; = _SimpleEncoder(data:encoder.data)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        tmpEncoder.codingPath.append(key)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; value.encode(to: tmpEncoder)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;If we run the test again the &lt;code&gt;Date&lt;/code&gt; still doesn&amp;rsquo;t get snagged by the error. It will be easier to hit inside the Keyed and Unkeyed containers first.&lt;/p&gt;
&lt;p&gt;I got the Keyed and Unkeyed encoding containers working by adding the relevant functions, starting with a convert function like there is for &lt;code&gt;Float&lt;/code&gt; and &lt;code&gt;Int&lt;/code&gt; in the &lt;code&gt;:Encoder&lt;/code&gt;.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//----  In :Encoder&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;convert&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; value:Date) -&amp;gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; value.ISO8601Format()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Then adding the wrapper functions to the encoding containers and updating the case statements&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//----  In :KeyedEncodingContainerProtocol&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;private&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;_insertDate&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; value: Date, atKey key:Key) &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; _insertValue(encoder.convert(value), atKey: key)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;mutating&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;encode&lt;/span&gt;&amp;lt;T&amp;gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; value: T, forKey key: Key) &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;where&lt;/span&gt; T: Encodable {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;switch&lt;/span&gt; value {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;case&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;value&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;as&lt;/span&gt; Date: &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; _insertDate(value, atKey: key)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//----  In :UnkeyedEncodingContainer&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;private&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;mutating&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;_appendDate&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; value:Date) &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; _appendValue(encoder.convert(value))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;mutating&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;encode&lt;/span&gt;&amp;lt;T&amp;gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; value: T, forKey key: Key) &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;where&lt;/span&gt; T: Encodable {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;switch&lt;/span&gt; value {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;case&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;value&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;as&lt;/span&gt; Date: &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; _appendDate(value)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Add Keyed and Unkeyed containers to the test:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;testDate&lt;/span&gt;() &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;encoder&lt;/span&gt; = SimpleCoder()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;date&lt;/span&gt; = Date()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//--------- SingleValue (STILL FAILS)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;dateString&lt;/span&gt; = date.ISO8601Format(.iso8601)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;encodedDate&lt;/span&gt; = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; encoder.encode(date)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    XCTAssertEqual(dateString, encodedDate)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//--------- Keyed (PASSES)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;MiniWithDate&lt;/span&gt;:Encodable {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;date&lt;/span&gt;:Date = Date()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;miniToTest&lt;/span&gt; = MiniWithDate()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;structExpected&lt;/span&gt; = &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;date:&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;miniToTest.date.ISO8601Format&lt;span style=&#34;color:#a6da95&#34;&gt;())&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;encodedStruct&lt;/span&gt; = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; encoder.encode(miniToTest)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    XCTAssertEqual(structExpected, encodedStruct)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//--------- Unkeyed (PASSES)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;dateArray&lt;/span&gt; = [Date(), Date(), Date(), Date()]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;arrayExpected&lt;/span&gt; = dateArray.enumerated().&lt;span style=&#34;color:#91d7e3&#34;&gt;map&lt;/span&gt; ({ index, value &lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;index&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;value.ISO8601Format&lt;span style=&#34;color:#a6da95&#34;&gt;())&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }).joined(separator: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;/&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;encodedArray&lt;/span&gt; = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; encoder.encode(dateArray)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    XCTAssertEqual(arrayExpected, encodedArray)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The Keyed and Unkeyed containers work and the SingleValue encoding container doesn&amp;rsquo;t hit the error! What gives?&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;Date&lt;/code&gt; keeps prioritizing its defaults (&lt;a href=&#34;https://github.com/apple/swift-corelibs-foundation/blob/1dac1132d49b0ee4213ac89473019cae8a608b5c/Sources/Foundation/Date.swift#L284&#34;&gt;core&lt;/a&gt; | &lt;a href=&#34;https://github.com/apple/swift-foundation/blob/69a6e9f4902f5043a89fbfa1da0e89a1ffe367fe/Sources/FoundationEssentials/Date.swift#L307&#34;&gt;FoundationEssential&lt;/a&gt;). I mentioned &lt;a href=&#34;https://whynotestflight.com/excuses/how-do-custom-encoders-work/#handle-dates&#34;&gt;date handling in the last post&lt;/a&gt;, that the URIEncoder &amp;amp; the JSONEncoders and even the XML encoder all have to catch a stand alone &lt;code&gt;Date&lt;/code&gt; value in their &lt;a href=&#34;https://github.com/apple/swift-openapi-runtime/blob/a875c2d45477be7a6d193ed3201603d05175d164/Sources/OpenAPIRuntime/URICoder/Encoding/URIValueToNodeEncoder.swift#L62&#34;&gt;encodeValue&lt;/a&gt;/&lt;a href=&#34;https://github.com/apple/swift-foundation/blob/69f473d8879ec494b4bcc5f97d091c2b5d263acb/Sources/FoundationEssentials/JSON/JSONEncoder.swift#L1112&#34;&gt;wrapGeneric&lt;/a&gt;/&lt;a href=&#34;https://github.com/CoreOffice/XMLCoder/blob/efda1cc8e0a97d198b6d16d53ff73751bd93f801/Sources/XMLCoder/Encoder/XMLEncoderImplementation.swift#L257&#34;&gt;box&lt;/a&gt; functions. It was good to see the need for that in action.&lt;/p&gt;
&lt;p&gt;Instead of a routing function inside the &lt;code&gt;_SimpleCoder:Encoder&lt;/code&gt;, I&amp;rsquo;ll put an array of types that I&amp;rsquo;ve made special handlers for up in the public &lt;code&gt;SimpleCoder&lt;/code&gt;. If my public function gets passed a value whose type is in that array, that&amp;rsquo;s when it will go to the special handler function inside the &lt;code&gt;:Encoder&lt;/code&gt;. Since &lt;code&gt;SimpleCoder&lt;/code&gt; is a learning exercise I want to contrast right up top why one might see the basic &lt;code&gt;value.encode(to: encoder)&lt;/code&gt; pattern (no overrides) vs. something more like &lt;code&gt;encoder.encode(for: value) -&amp;gt; some Output&lt;/code&gt; (overrides inside).&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//----  Updated&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;SimpleCoder&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;flaggedTypes&lt;/span&gt;:[Encodable.&lt;span style=&#34;color:#c6a0f6&#34;&gt;Type&lt;/span&gt;] = [Date.&lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;encode&lt;/span&gt;&amp;lt;E:Encodable&amp;gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; value: E) &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; -&amp;gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;encoder&lt;/span&gt; = _SimpleEncoder()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; flaggedTypes.&lt;span style=&#34;color:#91d7e3&#34;&gt;contains&lt;/span&gt;(&lt;span style=&#34;color:#c6a0f6&#34;&gt;where&lt;/span&gt;: { &lt;span style=&#34;color:#f4dbd6&#34;&gt;$0&lt;/span&gt; == E.&lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt; }) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; encoder.specialEncoder(&lt;span style=&#34;color:#c6a0f6&#34;&gt;for&lt;/span&gt;: value)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        } &lt;span style=&#34;color:#c6a0f6&#34;&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; value.encode(to: encoder)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; encoder.value
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//----  Added&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;extension&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;_SimpleEncoder&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;specialEncoder&lt;/span&gt;(&lt;span style=&#34;color:#c6a0f6&#34;&gt;for&lt;/span&gt; value: some Encodable) &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;container&lt;/span&gt; = singleValueContainer()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; container.encode(value)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//----  In the :SingleValueEncodingContainer&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;private&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;_setDate&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; value:Date) &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; _setValue(encoder.convert(value))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;mutating&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;encode&lt;/span&gt;&amp;lt;T&amp;gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; value: T, forKey key: Key) &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;where&lt;/span&gt; T: Encodable {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;switch&lt;/span&gt; value {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;case&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;value&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;as&lt;/span&gt; Date: &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; _setDate(value)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The &lt;code&gt;Date&lt;/code&gt; tests now all pass.&lt;/p&gt;
&lt;h2 id=&#34;fixing-urls&#34;&gt;Fixing URLs&lt;/h2&gt;
&lt;p&gt;I&amp;rsquo;m also going to need &lt;code&gt;URL&lt;/code&gt;s for the &lt;code&gt;Lines&lt;/code&gt; data and &lt;code&gt;URL&lt;/code&gt;s have an excessively complete default format for my needs. What do I mean? They come out looking like:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//singleValue&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;relative:http://www.example.com&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//part of Struct&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;url.relative:http://www.example.com&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//part of Array&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;0.relative:http://www.example.com/1.relative:http://www.example.com?testQuery=42/2.relative:http://www.example.com/3.relative:http://www.example.com&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;When a &lt;code&gt;URL&lt;/code&gt; gets created from any of the following possible init paths, it actually creates a key:value pair of the &lt;code&gt;String&lt;/code&gt; &amp;ldquo;relative&amp;rdquo; and the &lt;code&gt;URL&lt;/code&gt;&amp;rsquo;s &lt;code&gt;relativeString&lt;/code&gt;. See &lt;a href=&#34;https://forums.swift.org/t/how-to-encode-objects-of-unknown-type/12253/11&#34;&gt;a discussion&lt;/a&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;URL(string:&amp;quot;http://www.example.com&amp;quot;)&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;FileManager.default.homeDirectoryForCurrentUser&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;var components = URLComponents(); components.scheme = &amp;quot;http&amp;quot;; components.host = &amp;quot;www.example.com&amp;quot;; components.queryItems = [URLQueryItem(name: &amp;quot;testQuery&amp;quot;, value: &amp;quot;42&amp;quot;)]&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;URL(dataRepresentation: &amp;quot;http://www.example.com&amp;quot;.data(using: .utf8)!, relativeTo: nil, isAbsolute: true)&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Why is that? Well, lets look at the &lt;a href=&#34;https://github.com/apple/swift-corelibs-foundation/blob/3451ceb687f71f049f25d5ef93e5a48db93c523c/Sources/Foundation/URL.swift#L1021&#34;&gt;Codable implementation&lt;/a&gt; for URL:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;extension&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;URL&lt;/span&gt; : Codable {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;private&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;enum&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;CodingKeys&lt;/span&gt; : &lt;span style=&#34;color:#91d7e3&#34;&gt;Int&lt;/span&gt;, CodingKey {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;case&lt;/span&gt; base
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;case&lt;/span&gt; relative
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;init&lt;/span&gt;(from decoder: Decoder) &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;container&lt;/span&gt; = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; decoder.container(keyedBy: CodingKeys.&lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;relative&lt;/span&gt; = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; container.decode(&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;.&lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;, forKey: .relative)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;base&lt;/span&gt; = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; container.decodeIfPresent(URL.&lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;, forKey: .base)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;guard&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;url&lt;/span&gt; = URL(string: relative, relativeTo: base) &lt;span style=&#34;color:#c6a0f6&#34;&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;throw&lt;/span&gt; DecodingError.dataCorrupted(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                                   DecodingError.Context(codingPath: decoder.codingPath,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                                                         debugDescription: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Invalid URL string.&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                                )
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt; = url
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;encode&lt;/span&gt;(to encoder: Encoder) &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;container&lt;/span&gt; = encoder.container(keyedBy: CodingKeys.&lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; container.encode(&lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;.relativeString, forKey: .relative)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;base&lt;/span&gt; = &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;.baseURL {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; container.encode(base, forKey: .base)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;A complete &lt;code&gt;URL&lt;/code&gt; actually has two pieces of information. Its path and whether it&amp;rsquo;s relative to a different &lt;code&gt;URL&lt;/code&gt;. If one declares a &lt;code&gt;URL&lt;/code&gt; like:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;let relativeURL = URL(fileURLWithPath: &amp;quot;hello.jpg&amp;quot;, relativeTo: URL(string:&amp;quot;http://www.example.com&amp;quot;))&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;It does in fact produce the complete set when encoded:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;relative:hello.jpg/base.relative:http://www.example.com&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;For saving URLs to the &lt;code&gt;Lines&lt;/code&gt; data I just want the &lt;code&gt;URL&lt;/code&gt;&amp;rsquo;s &lt;code&gt;absoluteString&lt;/code&gt;, so I&amp;rsquo;ll need another &lt;code&gt;convert&lt;/code&gt; function.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;SimpleCoder&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;flaggedTypes&lt;/span&gt;:[Encodable.&lt;span style=&#34;color:#c6a0f6&#34;&gt;Type&lt;/span&gt;] = [Date.&lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;, URL.&lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;encode&lt;/span&gt;&amp;lt;E:Encodable&amp;gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; value: E) &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; -&amp;gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;encoder&lt;/span&gt; = _SimpleEncoder()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; flaggedTypes.&lt;span style=&#34;color:#91d7e3&#34;&gt;contains&lt;/span&gt;(&lt;span style=&#34;color:#c6a0f6&#34;&gt;where&lt;/span&gt;: { &lt;span style=&#34;color:#f4dbd6&#34;&gt;$0&lt;/span&gt; == E.&lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;}) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; encoder.specialEncoder(&lt;span style=&#34;color:#c6a0f6&#34;&gt;for&lt;/span&gt;: value)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        } &lt;span style=&#34;color:#c6a0f6&#34;&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; value.encode(to: encoder)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; encoder.value
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//----  In :Encoder&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;convert&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; value:URL) -&amp;gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; value.absoluteString()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//---- Also in all 3 encoding containers... Keyed example.  &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;private&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;_insertURL&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; value: URL, atKey key:Key) &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; _insertValue(encoder.convert(value), atKey: key)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}  
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;mutating&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;encode&lt;/span&gt;&amp;lt;T&amp;gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; value: T, forKey key: Key) &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;where&lt;/span&gt; T: Encodable {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;switch&lt;/span&gt; value {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;case&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;value&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;as&lt;/span&gt; URL: &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; _insertValue(value, forKey:Key)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And again the tests work!&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;testURL&lt;/span&gt;() &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;encoder&lt;/span&gt; = SimpleCoder()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//------------------ mostly HTTP Schema&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;http_url&lt;/span&gt; = URL(string: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;http://www.example.com&amp;#34;&lt;/span&gt;)&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;!&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;components&lt;/span&gt; = URLComponents()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    components.scheme = &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;http&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    components.host = &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;www.example.com&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    components.queryItems = [URLQueryItem(name: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;testQuery&amp;#34;&lt;/span&gt;, value: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;42&amp;#34;&lt;/span&gt;)]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;file_url&lt;/span&gt; = FileManager.&lt;span style=&#34;color:#c6a0f6&#34;&gt;default&lt;/span&gt;.homeDirectoryForCurrentUser
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;absoluteURL&lt;/span&gt; = URL(dataRepresentation: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;http://www.example.com&amp;#34;&lt;/span&gt;.data(using: .utf8)&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;!&lt;/span&gt;, 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                            relativeTo: &lt;span style=&#34;color:#f5a97f&#34;&gt;nil&lt;/span&gt;, isAbsolute: &lt;span style=&#34;color:#f5a97f&#34;&gt;true&lt;/span&gt;)&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;!&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;relativeURL&lt;/span&gt; = URL(fileURLWithPath: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;hello.jpg&amp;#34;&lt;/span&gt;, 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                            relativeTo: URL(string:&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;http://www.example.com&amp;#34;&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//does not even touch my encoder&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;httpUrlString&lt;/span&gt; = http_url.relativeString &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//.absoluteString&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;httpEncodedURL&lt;/span&gt; = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; encoder.encode(http_url)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    XCTAssertEqual(httpUrlString, httpEncodedURL)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//--------- Keyed&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;MiniWithHttpURL&lt;/span&gt;:Encodable {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;url&lt;/span&gt;:URL = URL(string: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;http://www.example.com&amp;#34;&lt;/span&gt;)&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;!&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;httpMiniToTest&lt;/span&gt; = MiniWithHttpURL()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;httpStructExpected&lt;/span&gt; = &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;url:&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;httpMiniToTest.url.absoluteString&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;httpEncodedStruct&lt;/span&gt; = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; encoder.encode(httpMiniToTest)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    XCTAssertEqual(httpStructExpected, httpEncodedStruct)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//--------- Unkeyed&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;urlArray&lt;/span&gt; = [http_url, components.url!, absoluteURL, relativeURL, file_url]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;httpArrayExpected&lt;/span&gt; = urlArray.enumerated().&lt;span style=&#34;color:#91d7e3&#34;&gt;map&lt;/span&gt; ({ index, value &lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;index&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;value.absoluteString&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }).joined(separator: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;/&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;encodedURLArray&lt;/span&gt; = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; encoder.encode(urlArray)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    XCTAssertEqual(httpArrayExpected, encodedURLArray)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;fixing-data&#34;&gt;Fixing Data&lt;/h2&gt;
&lt;p&gt;Failing initial test:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//FAILS&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//XCTAssertEqual failed: (&amp;#34;Cg8U&amp;#34;) is not equal to (&amp;#34;0:10/1:15/2:20&amp;#34;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;testData&lt;/span&gt;() &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;encoder&lt;/span&gt; = SimpleCoder()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;data&lt;/span&gt; = Data([&lt;span style=&#34;color:#f5a97f&#34;&gt;10&lt;/span&gt;, &lt;span style=&#34;color:#f5a97f&#34;&gt;15&lt;/span&gt;, &lt;span style=&#34;color:#f5a97f&#34;&gt;20&lt;/span&gt;])
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;dataString&lt;/span&gt; = data.base64EncodedString()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;encodedData&lt;/span&gt; = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; encoder.encode(data)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    XCTAssertEqual(dataString, encodedData)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;New convert:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;@inline(__always)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;convert&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; value:Data) &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; -&amp;gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; value.base64EncodedString()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ul&gt;
&lt;li&gt;Do the same song and dance in the three encoding containers done for &lt;code&gt;URL&lt;/code&gt; and &lt;code&gt;Date&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;add &lt;code&gt;Data.self&lt;/code&gt; to &lt;code&gt;flaggedTypes&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;And again passing complete test.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;testData&lt;/span&gt;() &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;encoder&lt;/span&gt; = SimpleCoder()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//------------------ SingleValue&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;data&lt;/span&gt; = Data([&lt;span style=&#34;color:#f5a97f&#34;&gt;10&lt;/span&gt;, &lt;span style=&#34;color:#f5a97f&#34;&gt;15&lt;/span&gt;, &lt;span style=&#34;color:#f5a97f&#34;&gt;20&lt;/span&gt;])
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;dataString&lt;/span&gt; = data.base64EncodedString()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;encodedData&lt;/span&gt; = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; encoder.encode(data)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    XCTAssertEqual(dataString, encodedData)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//--------- Keyed&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;MiniWithData&lt;/span&gt;:Encodable {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;myData&lt;/span&gt;:Data = Data([&lt;span style=&#34;color:#f5a97f&#34;&gt;10&lt;/span&gt;, &lt;span style=&#34;color:#f5a97f&#34;&gt;15&lt;/span&gt;, &lt;span style=&#34;color:#f5a97f&#34;&gt;20&lt;/span&gt;, &lt;span style=&#34;color:#f5a97f&#34;&gt;127&lt;/span&gt;, &lt;span style=&#34;color:#f5a97f&#34;&gt;0&lt;/span&gt;])
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;miniToTest&lt;/span&gt; = MiniWithData()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;structExpected&lt;/span&gt; = &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;myData:Cg8UfwA=&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;encodedStruct&lt;/span&gt; = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; encoder.encode(miniToTest)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    XCTAssertEqual(structExpected, encodedStruct)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//--------- Unkeyed&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;dataArray&lt;/span&gt; = [data, data, data, data]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;structArray&lt;/span&gt; = [miniToTest, miniToTest]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;arrayExpected&lt;/span&gt; = dataArray.enumerated().&lt;span style=&#34;color:#91d7e3&#34;&gt;map&lt;/span&gt; ({ index, value &lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;index&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;value.base64EncodedString&lt;span style=&#34;color:#a6da95&#34;&gt;())&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }).joined(separator: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;/&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;encodedArray&lt;/span&gt; = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; encoder.encode(dataArray)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    XCTAssertEqual(arrayExpected, encodedArray)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;structArrayExpected&lt;/span&gt; = &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;0.myData:Cg8UfwA=/1.myData:Cg8UfwA=&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;encodedStructArray&lt;/span&gt; = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; encoder.encode(structArray)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    XCTAssertEqual(structArrayExpected, encodedStructArray)     
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Not hard to pull off, but one can see that having to go in to every encoding container to add every little new custom override would get annoying so when I do the &lt;code&gt;LineCoder&lt;/code&gt; I&amp;rsquo;ll handle it a little differently.&lt;/p&gt;
&lt;h2 id=&#34;what-to-do-about-optionals&#34;&gt;What to do about Optionals?&lt;/h2&gt;
&lt;p&gt;There are three ways to handle Optionals in an Encoder&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;add a specific marker for null values (put something in &lt;code&gt;encodeNil(forKey key: Key)&lt;/code&gt; func)&lt;/li&gt;
&lt;li&gt;silently ignore (put nothing in the &lt;code&gt;encodeNil(forKey key: Key)&lt;/code&gt; func)&lt;/li&gt;
&lt;li&gt;add &lt;code&gt;encodeIfPresent()&lt;/code&gt; versions of the functions
&lt;ul&gt;
&lt;li&gt;see &lt;a href=&#34;https://github.com/apple/swift-corelibs-foundation/blob/1dac1132d49b0ee4213ac89473019cae8a608b5c/Sources/Foundation/DateComponents.swift#L455&#34;&gt;DateComponents&amp;rsquo; codable conformance&lt;/a&gt; for an encoder using them.&lt;/li&gt;
&lt;li&gt;more info since I don&amp;rsquo;t go this route: &lt;a href=&#34;https://forums.swift.org/search?q=encodeIfPresent&#34;&gt;https://forums.swift.org/search?q=encodeIfPresent&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;And one can choose differently per container. Maybe a place holder makes sense for SingleValue situations, but Keyed null values can just be ignored. That&amp;rsquo;s the route I picked for SimpleCoder. It causes some interesting trouble for &lt;a href=&#34;https://github.com/carlynorama/CoderExplorer/blob/4d5cb306a623cce40076302fe7ca58ffefbde923/Tests/CoderExplorerTests/SimpleCoderTests.swift#L436&#34;&gt;enums with optional associated values in arrays&lt;/a&gt;, but that&amp;rsquo;s for fixing another day.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//In KeyedEncodingContainer&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;mutating&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;encodeNil&lt;/span&gt;(forKey key: Key) &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//do nothing. &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//try _insertValue(&amp;#34;NULL&amp;#34;, atKey: key)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//In SingleValueEncodingContainer&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;encodeNil&lt;/span&gt;() &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; { &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; _setValue(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;NULL&amp;#34;&lt;/span&gt;) }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//In UnkeyedEncodingContainer&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//That&amp;#39;s right. NOTHING in the test calls this. &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//Not even the nested Optional arrays. &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   &lt;span style=&#34;color:#c6a0f6&#34;&gt;mutating&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;encodeNil&lt;/span&gt;() &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#91d7e3&#34;&gt;fatalError&lt;/span&gt;()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//try _appendValue(&amp;#34;NULL&amp;#34;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;testBasicNil&lt;/span&gt;() &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;encoder&lt;/span&gt; = SimpleCoder()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//------------------ SingleValue&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;optionalValue&lt;/span&gt;:&lt;span style=&#34;color:#91d7e3&#34;&gt;Int&lt;/span&gt;? = &lt;span style=&#34;color:#f5a97f&#34;&gt;nil&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;optionalString&lt;/span&gt; = &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;NULL&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;encodedOptional&lt;/span&gt; = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; encoder.encode(optionalValue)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        XCTAssertEqual(optionalString, encodedOptional)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//--------- Keyed&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;MiniStruct&lt;/span&gt;:Encodable {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;noneInt&lt;/span&gt;:&lt;span style=&#34;color:#91d7e3&#34;&gt;Int&lt;/span&gt;? = &lt;span style=&#34;color:#f5a97f&#34;&gt;nil&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;someInt&lt;/span&gt;:&lt;span style=&#34;color:#91d7e3&#34;&gt;Int&lt;/span&gt;? = &lt;span style=&#34;color:#f5a97f&#34;&gt;12&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;miniToTest&lt;/span&gt; = MiniStruct()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;structExpected&lt;/span&gt; = &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;someInt:12&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;encodedStruct&lt;/span&gt; = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; encoder.encode(miniToTest)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        XCTAssertEqual(structExpected, encodedStruct)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;renderArray&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; array:[&lt;span style=&#34;color:#91d7e3&#34;&gt;Int&lt;/span&gt;?], prepend:&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt; = &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;) -&amp;gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            array.enumerated().&lt;span style=&#34;color:#91d7e3&#34;&gt;map&lt;/span&gt; ({ index, value &lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;valueString&lt;/span&gt; = value &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;!=&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;nil&lt;/span&gt; ? &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;value!&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt; : &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;NULL&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;prepend&lt;span style=&#34;color:#a6da95&#34;&gt;)\(&lt;/span&gt;index&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;valueString&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            }).joined(separator: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;/&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//--------- Unkeyed&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;array&lt;/span&gt; = [&lt;span style=&#34;color:#f5a97f&#34;&gt;10&lt;/span&gt;, &lt;span style=&#34;color:#f5a97f&#34;&gt;nil&lt;/span&gt;, &lt;span style=&#34;color:#f5a97f&#34;&gt;20&lt;/span&gt;, &lt;span style=&#34;color:#f5a97f&#34;&gt;nil&lt;/span&gt;, &lt;span style=&#34;color:#f5a97f&#34;&gt;0&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;arrayExpected&lt;/span&gt; = renderArray(array)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;encodedArray&lt;/span&gt; = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; encoder.encode(array)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        XCTAssertEqual(arrayExpected, encodedArray)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;subArray&lt;/span&gt;:[[&lt;span style=&#34;color:#91d7e3&#34;&gt;Int&lt;/span&gt;?]?] = [array, &lt;span style=&#34;color:#f5a97f&#34;&gt;nil&lt;/span&gt;, array]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;subArrayExpected&lt;/span&gt; = subArray.enumerated().&lt;span style=&#34;color:#91d7e3&#34;&gt;map&lt;/span&gt;({
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;notNil&lt;/span&gt; = &lt;span style=&#34;color:#f4dbd6&#34;&gt;$1&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; renderArray(notNil, prepend: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;$0&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;.&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            } &lt;span style=&#34;color:#c6a0f6&#34;&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;$0&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;:NULL&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            }).joined(separator: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;/&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;encodedSubArray&lt;/span&gt; = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; encoder.encode(subArray)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        XCTAssertEqual(subArrayExpected, encodedSubArray)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;MiniArrayStruct&lt;/span&gt;:Encodable {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;myIntArray&lt;/span&gt;:[&lt;span style=&#34;color:#91d7e3&#34;&gt;Int&lt;/span&gt;?] = [&lt;span style=&#34;color:#f5a97f&#34;&gt;10&lt;/span&gt;, &lt;span style=&#34;color:#f5a97f&#34;&gt;nil&lt;/span&gt;, &lt;span style=&#34;color:#f5a97f&#34;&gt;20&lt;/span&gt;, &lt;span style=&#34;color:#f5a97f&#34;&gt;nil&lt;/span&gt;, &lt;span style=&#34;color:#f5a97f&#34;&gt;0&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;miniArratStructToTest&lt;/span&gt; = MiniArrayStruct()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;structArray&lt;/span&gt; = [miniArratStructToTest, miniArratStructToTest]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;structArrayExpected&lt;/span&gt; = structArray.enumerated().&lt;span style=&#34;color:#91d7e3&#34;&gt;map&lt;/span&gt; ({ index, value &lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            renderArray(value.myIntArray, prepend: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;index&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;.myIntArray.&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }).joined(separator: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;/&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;encodedStructArray&lt;/span&gt; = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; encoder.encode(structArray)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        XCTAssertEqual(structArrayExpected, encodedStructArray)   
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;adding-enums&#34;&gt;Adding enums&lt;/h2&gt;
&lt;h3 id=&#34;rawrepresentable&#34;&gt;RawRepresentable&lt;/h3&gt;
&lt;p&gt;When getting started with &lt;code&gt;enum&lt;/code&gt;&amp;rsquo;s it&amp;rsquo;s very useful to dive into the actual original swift-evolution proposal for what was called &amp;ldquo;&lt;a href=&#34;https://github.com/apple/swift-evolution/blob/1b0b339bc3072a83b5a6a529ae405a0f076c7d5d/proposals/0166-swift-archival-serialization.md?plain=1&#34;&gt;swift-archival-serialization&lt;/a&gt;&amp;rdquo; and jump to the place where it shows what the &lt;a href=&#34;https://github.com/apple/swift-evolution/blob/1b0b339bc3072a83b5a6a529ae405a0f076c7d5d/proposals/0166-swift-archival-serialization.md?plain=1#L666&#34;&gt;synthesized conformance for enums&lt;/a&gt; would be.&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;    public func encode(to encoder: Encoder) throws {
        // Encode as a single value; no keys.
        try encoder.singleValueContainer().encode(self.rawValue)
    }
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;An enum always gets pushed through to a singleValueContainer.&lt;/p&gt;
&lt;p&gt;And if we test this with  a &lt;code&gt;RawRepresentable&lt;/code&gt; conforming enum with a &lt;code&gt;RawValue&lt;/code&gt; of &lt;code&gt;String&lt;/code&gt; we see it works perfectly:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;testEnum&lt;/span&gt;() &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;encoder&lt;/span&gt; = SimpleCoder()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;enum&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;Greeting&lt;/span&gt;:&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;,Codable {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;case&lt;/span&gt; hello, howdy, hola, hi, hiya
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//------------------ SingleValue&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;enumValue&lt;/span&gt;:Greeting = .hiya
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;expectedEnumString&lt;/span&gt; = &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;hiya&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;encodedEnum&lt;/span&gt; = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; encoder.encode(enumValue)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        XCTAssertEqual(expectedEnumString, encodedEnum)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;but add an enum to a struct or array&amp;hellip;&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;MiniWithEnum&lt;/span&gt;:Encodable {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;otherValue&lt;/span&gt;:&lt;span style=&#34;color:#91d7e3&#34;&gt;Double&lt;/span&gt; = &lt;span style=&#34;color:#f5a97f&#34;&gt;42&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;myGreeting&lt;/span&gt;:Greeting = .hello
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;otherStringValue&lt;/span&gt; = &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;world&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;miniToTest&lt;/span&gt; = MiniWithEnum()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;structExpected&lt;/span&gt; = &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;myGreeting:&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;miniToTest.myGreeting&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;/otherStringValue:world/otherValue:42.0&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;encodedStruct&lt;/span&gt; = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; encoder.encode(miniToTest)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        XCTAssertEqual(structExpected, encodedStruct)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//--------- Unkeyed&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;enumArray&lt;/span&gt;:[Greeting] = [.hello, .howdy, .hiya, .hola]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;arrayExpected&lt;/span&gt; = enumArray.enumerated().&lt;span style=&#34;color:#91d7e3&#34;&gt;map&lt;/span&gt; ({ index, value &lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;index&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;value&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }).joined(separator: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;/&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;encodedArray&lt;/span&gt; = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; encoder.encode(enumArray)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        XCTAssertEqual(arrayExpected, encodedArray)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And we get failures like:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;XCTAssertEqual failed: (&amp;#34;myGreeting:hello/otherStringValue:world/otherValue:42.0&amp;#34;) is not equal to (&amp;#34;hello/otherStringValue:world/otherValue:42.0&amp;#34;)
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;What happened? Well, even though I&amp;rsquo;m in a keyed container, my default behavior for anything my encoder doesn&amp;rsquo;t recognize is to let it do its own thing. For an enum that means it&amp;rsquo;s going through a &lt;code&gt;SingleValueEncodingContainer&lt;/code&gt; (&lt;a href=&#34;https://forums.swift.org/t/enum-codable-bug/39693&#34;&gt;See this discussion&lt;/a&gt;).  In the data store it does have a key, but it&amp;rsquo;s &lt;code&gt;myGreeting.keyless(some UUID)&lt;/code&gt; which gets stripped out in our serialization step because it contains the text &amp;ldquo;keyless&amp;rdquo;.&lt;/p&gt;
&lt;p&gt;I have some choices:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;figure out a way to intercept all enums&lt;/li&gt;
&lt;li&gt;write custom codable conformance for any enums to use with this encoder&lt;/li&gt;
&lt;li&gt;Fix the &lt;code&gt;Dictionary -&amp;gt; String&lt;/code&gt; step&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I&amp;rsquo;m going to update the &lt;code&gt;Dictionary -&amp;gt; String&lt;/code&gt; creation code because it will be easier than rerouting all enums or guaranteeing custom Codable implementations. Also my data store really relies on those unique keys so I can&amp;rsquo;t change the key-encoding function either.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;value&lt;/span&gt;:&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;lines&lt;/span&gt; = data.storage.&lt;span style=&#34;color:#91d7e3&#34;&gt;map&lt;/span&gt; { key, value &lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;mKey&lt;/span&gt; = key
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; mKey.&lt;span style=&#34;color:#91d7e3&#34;&gt;contains&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;keyless&amp;#34;&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                mKey = cleanKey(mKey)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; mKey.&lt;span style=&#34;color:#91d7e3&#34;&gt;isEmpty&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;              &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;value&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            } &lt;span style=&#34;color:#c6a0f6&#34;&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;              &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;mKey&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;value&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        lines.&lt;span style=&#34;color:#91d7e3&#34;&gt;sort&lt;/span&gt;()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; lines.joined(separator: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;/&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;cleanKey&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; key:&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;, keyDelimiter:&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;.Element = &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;.&amp;#34;&lt;/span&gt;) -&amp;gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//potential alternative approach:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//just trim from the end until the last delimiter. &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//TBD if there is a case where that would make a difference since the SVEC &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//create a nested container. &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;split&lt;/span&gt; = key.&lt;span style=&#34;color:#91d7e3&#34;&gt;split&lt;/span&gt;(whereSeparator: { &lt;span style=&#34;color:#f4dbd6&#34;&gt;$0&lt;/span&gt; == keyDelimiter }).&lt;span style=&#34;color:#91d7e3&#34;&gt;filter&lt;/span&gt;({ &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;!&lt;/span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;$0&lt;/span&gt;.&lt;span style=&#34;color:#91d7e3&#34;&gt;contains&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;keyless&amp;#34;&lt;/span&gt;)})
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;split&lt;/span&gt;.joined(separator: &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;(keyDelimiter))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And now it all works.&lt;/p&gt;
&lt;h3 id=&#34;unspecified-enum&#34;&gt;Unspecified Enum&lt;/h3&gt;
&lt;p&gt;What happens when the enum isn&amp;rsquo;t &lt;code&gt;RawRepresentable&lt;/code&gt; with a &lt;code&gt;RawValue&lt;/code&gt; of &lt;code&gt;String&lt;/code&gt; or &lt;code&gt;Int&lt;/code&gt;?&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;testPlainEnum&lt;/span&gt;() &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;encoder&lt;/span&gt; = SimpleCoder()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;enum&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;FruitChoice&lt;/span&gt;:Codable {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;case&lt;/span&gt; strawberry, pineapple, dragon, kiwi, kumquat
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//------------------ SingleValue&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;enumFruitValue&lt;/span&gt;:FruitChoice = .strawberry
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;expectedEnumFruitString&lt;/span&gt; = &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;strawberry&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;encodedFruitEnum&lt;/span&gt; = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; encoder.encode(enumFruitValue)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        XCTAssertEqual(expectedEnumFruitString, encodedFruitEnum) 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Whelp. It catches one of the remaining &lt;code&gt;fatalErrors()&lt;/code&gt; in the SimpleEncoderKEC at&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;mutating&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;nestedContainer&lt;/span&gt;&amp;lt;NestedKey&amp;gt;(keyedBy keyType: NestedKey.&lt;span style=&#34;color:#c6a0f6&#34;&gt;Type&lt;/span&gt;, forKey key: Key)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        -&amp;gt; KeyedEncodingContainer&amp;lt;NestedKey&amp;gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;where&lt;/span&gt; NestedKey: CodingKey
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#91d7e3&#34;&gt;fatalError&lt;/span&gt;()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;replacing that with&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;mutating&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;nestedContainer&lt;/span&gt;&amp;lt;NestedKey&amp;gt;(keyedBy keyType: NestedKey.&lt;span style=&#34;color:#c6a0f6&#34;&gt;Type&lt;/span&gt;, forKey key: Key)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        -&amp;gt; KeyedEncodingContainer&amp;lt;NestedKey&amp;gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;where&lt;/span&gt; NestedKey: CodingKey
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//fatalError()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;nestedKey:&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;key.stringValue&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; encoder.container(keyedBy: NestedKey.&lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;One gets the TestFailure, AND one gets to see the reason for it; the enum values are coming through as the keys this time.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Test Case 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;#39;-[CoderExplorerTests.CodeableStringExample testPlainEnum]&amp;#39; started.
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;nestedKey:strawberry
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;CoderExplorer/Tests/CoderExplorerTests/SimpleCoderTests.swift:251: 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;error: -[CoderExplorerTests.CodableStringExample testPlainEnum] :
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;XCTAssertEqual failed: (&amp;#34;strawberry&amp;#34;) is not equal to (&amp;#34;&amp;#34;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;If I sent this enum to the JSONEncoder, it could handle it. The value would be an empty object.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;enum&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;FruitChoice&lt;/span&gt;:Encodable {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;case&lt;/span&gt; strawberry, pineapple, dragon, kiwi, kumquat
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;JSONencoder&lt;/span&gt; = JSONEncoder()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;encodedData&lt;/span&gt; = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; JSONencoder.encode(FruitChoice.strawberry)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;string&lt;/span&gt; = &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;(bytes: encodedData, encoding: .utf8) ?? &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//string == {&amp;#34;strawberry&amp;#34;:{}}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;It would actually take some significant doing to catch an empty object in this particular encoder, so I&amp;rsquo;m going to show &amp;ldquo;fixing&amp;rdquo; the enum instead. These enums will no longer call the &lt;code&gt;nestedContainer&amp;lt;NestedKey&amp;gt;(keyedBy:forKey:)&lt;/code&gt; function because the the custom &lt;code&gt;encode(to:)&lt;/code&gt; function (as opposed to the synthesized one) knows the enum is flat and has no associated values.&lt;/p&gt;
&lt;h4 id=&#34;option-1-stripping-the-key-entirely&#34;&gt;Option 1: Stripping the key entirely&lt;/h4&gt;
&lt;p&gt;The right thing to do would be to make it &lt;code&gt;RawRepresentable&lt;/code&gt; as a &lt;code&gt;String&lt;/code&gt; as seen above, but if for some reason you can&amp;rsquo;t or want to have more control over the returned string:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;enum&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;FruitChoice&lt;/span&gt;:Encodable {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;case&lt;/span&gt; strawberry, pineapple, dragon, kiwi, kumquat
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;encode&lt;/span&gt;(to encoder: Encoder) &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;container&lt;/span&gt; = encoder.singleValueContainer()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; container.encode(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;&lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h4 id=&#34;option-2-forcing-a-keyvalue-pair&#34;&gt;Option 2: Forcing a key:value pair&lt;/h4&gt;
&lt;p&gt;Maybe instead the enum name would be useful to have in the data for some reason. The enum can return a dictionary.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;enum&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;FruitChoice&lt;/span&gt;:Encodable {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;case&lt;/span&gt; strawberry, pineapple, dragon, kiwi, kumquat
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;encode&lt;/span&gt;(to encoder: Encoder) &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//really a dictionary, but JSON terminology is leaking in&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;asObject&lt;/span&gt; = [&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;FruitChoice&amp;#34;&lt;/span&gt;:&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;&lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;container&lt;/span&gt; = encoder.singleValueContainer()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;container&lt;/span&gt; = 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; container.encode(asObject)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h4 id=&#34;option-3-updating-the-codingkeys-the-right-way&#34;&gt;Option 3: updating the CodingKeys (the &amp;ldquo;right way&amp;rdquo;)&lt;/h4&gt;
&lt;p&gt;Strictly more correct than the above method?&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;enum&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;CodingKeys&lt;/span&gt;:CodingKey {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;case&lt;/span&gt; fruitChoice
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;encode&lt;/span&gt;(to encoder: Encoder) &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;container&lt;/span&gt; = encoder.container(keyedBy: &lt;span style=&#34;color:#f5a97f&#34;&gt;Self&lt;/span&gt;.CodingKeys.&lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; container.encode(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;&lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;, forKey: .fruitChoice)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;associated-values&#34;&gt;Associated Values&lt;/h3&gt;
&lt;p&gt;Newish to Codable is &amp;ldquo;Codable Synthesis for Enums with Associated Values&amp;rdquo;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Proposal
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/apple/swift-evolution/blob/main/proposals/0295-codable-synthesis-for-enums-with-associated-values.md&#34;&gt;on GitHub&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://forums.swift.org/t/se-0295-codable-synthesis-for-enums-with-associated-values/42408/&#34;&gt;on Forum&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Adding a mix of associated values to FruitChoice, what one will get is position based &lt;a href=&#34;https://github.com/apple/swift-evolution/blob/1b0b339bc3072a83b5a6a529ae405a0f076c7d5d/proposals/0295-codable-synthesis-for-enums-with-associated-values.md?plain=1#L70&#34;&gt;synthesized keys&lt;/a&gt; for the sub-object Swift thinks the associated value is part of.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;enum&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;FruitChoice&lt;/span&gt;:Encodable {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;case&lt;/span&gt; strawberry(&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;, &lt;span style=&#34;color:#91d7e3&#34;&gt;Int&lt;/span&gt;), 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;case&lt;/span&gt; pineapple(&lt;span style=&#34;color:#91d7e3&#34;&gt;Int&lt;/span&gt;), 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;case&lt;/span&gt; dragon(&lt;span style=&#34;color:#91d7e3&#34;&gt;Double&lt;/span&gt;), 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;case&lt;/span&gt; kiwi(&lt;span style=&#34;color:#91d7e3&#34;&gt;UInt8&lt;/span&gt;), 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;case&lt;/span&gt; kumquat(Date)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;JSONencoder&lt;/span&gt; = JSONEncoder()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;encodedData&lt;/span&gt; = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; JSONencoder.encode(FruitChoice.strawberry(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Everbearing&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#f5a97f&#34;&gt;5&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;string&lt;/span&gt; = &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;(bytes: encodedData, encoding: .utf8) ?? &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//&amp;#34;{&amp;#34;strawberry&amp;#34;:{&amp;#34;_0&amp;#34;:&amp;#34;Everbearing&amp;#34;,&amp;#34;_1&amp;#34;:5}}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;One can name them inline:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;enum&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;FruitChoice&lt;/span&gt;:Encodable {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;case&lt;/span&gt; strawberry(name:&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;, cropCount:&lt;span style=&#34;color:#91d7e3&#34;&gt;Int&lt;/span&gt;), 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;case&lt;/span&gt; pineapple(yearsToFruit:&lt;span style=&#34;color:#91d7e3&#34;&gt;Int&lt;/span&gt;), 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;case&lt;/span&gt; dragon(metersTall:&lt;span style=&#34;color:#91d7e3&#34;&gt;Double&lt;/span&gt;), 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;case&lt;/span&gt; kiwi(seedsIn1mmSlice:&lt;span style=&#34;color:#91d7e3&#34;&gt;UInt8&lt;/span&gt;), 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;case&lt;/span&gt; kumquat(whenAquired:Date)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Or override the whole synthesized Codable conformance:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;enum&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;FruitChoice&lt;/span&gt;:Encodable {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;case&lt;/span&gt; strawberry(&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;, &lt;span style=&#34;color:#91d7e3&#34;&gt;Int&lt;/span&gt;), pineapple(&lt;span style=&#34;color:#91d7e3&#34;&gt;Double&lt;/span&gt;), kumquat(Date)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;enum&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;CodingKeys&lt;/span&gt;:CodingKey {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;case&lt;/span&gt; strawberry
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;case&lt;/span&gt; pineapple
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;case&lt;/span&gt; kumquat
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;     &lt;span style=&#34;color:#ed8796&#34;&gt;enum&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;StrawberryCodingKeys&lt;/span&gt;: CodingKey {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;case&lt;/span&gt; name
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;case&lt;/span&gt; cropCount
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;enum&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;PineappleCodingKeys&lt;/span&gt;: CodingKey {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;       &lt;span style=&#34;color:#c6a0f6&#34;&gt;case&lt;/span&gt; yearsToFruit
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;     }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;enum&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;KumquatCodingKeys&lt;/span&gt;: CodingKey {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;case&lt;/span&gt; dateAquired
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;encode&lt;/span&gt;(to encoder: Encoder) &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;container&lt;/span&gt; = encoder.container(keyedBy: CodingKeys.&lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#c6a0f6&#34;&gt;switch&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#c6a0f6&#34;&gt;case&lt;/span&gt; .strawberry(&lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;string&lt;/span&gt;, &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;int&lt;/span&gt;): 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;nestedContainer&lt;/span&gt; = container.nestedContainer(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                                                keyedBy: StrawberryCodingKeys.&lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;, 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                                                forKey: .strawberry)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; nestedContainer.encode(string, forKey: .name)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; nestedContainer.encode(int, forKey: .cropCount)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#c6a0f6&#34;&gt;case&lt;/span&gt; .pineapple(&lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;double&lt;/span&gt;): 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;nestedContainer&lt;/span&gt; = container.nestedContainer(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                                                keyedBy: PineappleCodingKeys.&lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;, 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                                                forKey: .pineapple)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; nestedContainer.encode(double, forKey: .yearsToFruit)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#c6a0f6&#34;&gt;case&lt;/span&gt; .kumquat(&lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;date&lt;/span&gt;):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;nestedContainer&lt;/span&gt; = container.nestedContainer(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                                                keyedBy: KumquatCodingKeys.&lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;, 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                                                forKey: .kumquat)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; nestedContainer.encode(date, forKey: .dateAquired)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;I include that mostly to show how the nestedContainer call comes into play. Now that I&amp;rsquo;ll be needing that function again I have to fix it to work correctly.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;mutating&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;nestedContainer&lt;/span&gt;&amp;lt;NestedKey&amp;gt;(keyedBy keyType: NestedKey.&lt;span style=&#34;color:#c6a0f6&#34;&gt;Type&lt;/span&gt;, forKey key: Key)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        -&amp;gt; KeyedEncodingContainer&amp;lt;NestedKey&amp;gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;where&lt;/span&gt; NestedKey: CodingKey
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//have to reversibly push the key onto the stack. &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;tmpEncoder&lt;/span&gt; = _SimpleEncoder(data:encoder.data)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        tmpEncoder.codingPath = encoder.codingPath
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        tmpEncoder.codingPath.append(key)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; tmpEncoder.container(keyedBy: NestedKey.&lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;I&amp;rsquo;ll add that to all the &lt;code&gt;nestedContainer(keyType:forKey:)&lt;/code&gt; calls. I&amp;rsquo;m creating a new &lt;code&gt;_SimpleCoder&lt;/code&gt; in at least 5 places and counting now so I&amp;rsquo;ll make a function to do it:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// in _SimpleCoder&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;typealias&lt;/span&gt; DataStore = SimpleCoderData&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;lt;&lt;/span&gt;[&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;: &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;]&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;getEncoder&lt;/span&gt;(forKey key:CodingKey?, withData passedInData:DataStore) -&amp;gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;Self&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;tmp&lt;/span&gt; = _SimpleEncoder(data:passedInData)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        tmp.codingPath = &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;.codingPath
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;key&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            tmp.codingPath.append(key)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; tmp
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;In &lt;code&gt;_SimpleCoder&lt;/code&gt; the data storage never gets wiped clean so I could just use &lt;code&gt;self.data&lt;/code&gt; in the function without passing it through, but I&amp;rsquo;d like to make it clear at the call location that the data matters for my own future reference.&lt;/p&gt;
&lt;p&gt;For more about nested containers see also&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/apple/swift-corelibs-foundation/blob/1dac1132d49b0ee4213ac89473019cae8a608b5c/Sources/Foundation/Measurement.swift#L313&#34;&gt;Measurement&amp;rsquo;s Encodable conformance&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/apple/swift-corelibs-foundation/blob/1dac1132d49b0ee4213ac89473019cae8a608b5c/Sources/Foundation/IndexSet.swift#L925&#34;&gt;IndexSet&amp;rsquo;s Encodable conformance&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The tests pass!&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;testAssociateValueEnum&lt;/span&gt;() &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;enum&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;FruitChoice&lt;/span&gt;:Encodable {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;case&lt;/span&gt; strawberry(name:&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;, cropCount:&lt;span style=&#34;color:#91d7e3&#34;&gt;Int&lt;/span&gt;), 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;case&lt;/span&gt; pineapple(yearsToFruit:&lt;span style=&#34;color:#91d7e3&#34;&gt;Double&lt;/span&gt;), 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;case&lt;/span&gt; kumquat(dateAcquired:Date)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//------------------ SingleValue&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;enumFruitValue&lt;/span&gt;:FruitChoice = .strawberry(name:&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Everbearing&amp;#34;&lt;/span&gt;, cropCount:&lt;span style=&#34;color:#f5a97f&#34;&gt;6&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;expectedEnumFruitString&lt;/span&gt; = &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;strawberry.cropCount:6/strawberry.name:Everbearing&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;encodedFruitEnum&lt;/span&gt; = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; encoder.encode(enumFruitValue)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        XCTAssertEqual(expectedEnumFruitString, encodedFruitEnum)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//--------- Keyed&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;MiniWithEnum&lt;/span&gt;:Encodable {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;otherValue&lt;/span&gt;:&lt;span style=&#34;color:#91d7e3&#34;&gt;Double&lt;/span&gt; = &lt;span style=&#34;color:#f5a97f&#34;&gt;42&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;myFruit&lt;/span&gt;:FruitChoice = .pineapple(yearsToFruit:&lt;span style=&#34;color:#f5a97f&#34;&gt;3.12&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;otherStringValue&lt;/span&gt; = &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;world&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;miniToTest&lt;/span&gt; = MiniWithEnum()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;structExpected&lt;/span&gt; = &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;myFruit.pineapple.yearsToFruit:3.12/otherStringValue:world/otherValue:42.0&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;encodedStruct&lt;/span&gt; = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; encoder.encode(miniToTest)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        XCTAssertEqual(structExpected, encodedStruct)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//--------- Unkeyed&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;enumArray&lt;/span&gt;:[FruitChoice] = [.strawberry(name:&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Everbearing&amp;#34;&lt;/span&gt;, cropCount:&lt;span style=&#34;color:#f5a97f&#34;&gt;6&lt;/span&gt;),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                                       .pineapple(yearsToFruit:&lt;span style=&#34;color:#f5a97f&#34;&gt;1.23343&lt;/span&gt;), 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                                       .kumquat(dateAcquired:&lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; Date(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;2024-03-10T21:36:24Z&amp;#34;&lt;/span&gt;, 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                                                                      strategy: .iso8601))]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//        let arrayExpected = enumArray.enumerated().map ({ index, value in&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//            &amp;#34;\(index).fruitChoice:\(value)&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//        }).joined(separator: &amp;#34;/&amp;#34;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;arrayExpected&lt;/span&gt; = &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;0.strawberry.cropCount:6/&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;+&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;0.strawberry.name:Everbearing/&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;+&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;1.pineapple.yearsToFruit:1.23343/&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;+&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;2.kumquat.dateAquired:2024-03-10T21:36:24Z&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;encodedArray&lt;/span&gt; = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; encoder.encode(enumArray)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        XCTAssertEqual(arrayExpected, encodedArray)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;adding-a-dictionary&#34;&gt;Adding a Dictionary&lt;/h2&gt;
&lt;p&gt;Using dictionaries that have an &lt;code&gt;Int&lt;/code&gt; or &lt;code&gt;String&lt;/code&gt; as a key and &lt;code&gt;some Encodable&lt;/code&gt; as their value works like a charm. I&amp;rsquo;m not going to spend any time on them except to mention, yes, &lt;a href=&#34;https://github.com/carlynorama/CoderExplorer/blob/4d5cb306a623cce40076302fe7ca58ffefbde923/Tests/CoderExplorerTests/SimpleCoderTests.swift#L486&#34;&gt;I wrote a test&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;One can get other types to work as codable dictionary keys by conforming them to &lt;code&gt;CodingKeyRepresentable&lt;/code&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/apple/swift-evolution/blob/main/proposals/0320-codingkeyrepresentable.md&#34;&gt;https://github.com/apple/swift-evolution/blob/main/proposals/0320-codingkeyrepresentable.md&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://forums.swift.org/t/pitch-allow-coding-of-non-string-int-keyed-dictionary-into-a-keyedcontainer/44593&#34;&gt;https://forums.swift.org/t/pitch-allow-coding-of-non-string-int-keyed-dictionary-into-a-keyedcontainer/44593&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Many of the fixed-width int types conform automatically, but &lt;a href=&#34;https://forums.swift.org/t/why-doesnt-int64-automatically-conform-to-codingkeyrepresentable/62073&#34;&gt;not all of them do or should&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;A passing test&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;testSomeEncodableKeyDictionary&lt;/span&gt;() &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   &lt;span style=&#34;color:#ed8796&#34;&gt;enum&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;FruitKey&lt;/span&gt;:&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;, Codable, CodingKeyRepresentable {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;       &lt;span style=&#34;color:#c6a0f6&#34;&gt;case&lt;/span&gt; strawberry, banana, kiwi
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;dictionaryA&lt;/span&gt;:&lt;span style=&#34;color:#91d7e3&#34;&gt;Dictionary&lt;/span&gt;&amp;lt;FruitKey,&lt;span style=&#34;color:#91d7e3&#34;&gt;UInt32&lt;/span&gt;&amp;gt; = [
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;       .strawberry:&lt;span style=&#34;color:#f5a97f&#34;&gt;1&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;       .banana:&lt;span style=&#34;color:#f5a97f&#34;&gt;2&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;       .kiwi: &lt;span style=&#34;color:#f5a97f&#34;&gt;3&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   ]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   &lt;span style=&#34;color:#ed8796&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;FlowerCodingKey&lt;/span&gt;: CodingKey {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;       &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;stringValue&lt;/span&gt;: &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;       &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;intValue&lt;/span&gt;: &lt;span style=&#34;color:#91d7e3&#34;&gt;Int&lt;/span&gt;?
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;       
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;       &lt;span style=&#34;color:#ed8796&#34;&gt;init&lt;/span&gt;?(stringValue: &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;) {  &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;.stringValue = stringValue  }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;       &lt;span style=&#34;color:#ed8796&#34;&gt;init&lt;/span&gt;?(intValue: &lt;span style=&#34;color:#91d7e3&#34;&gt;Int&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;           &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;.stringValue = &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;(intValue)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;           &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;.intValue = intValue
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;       }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;       &lt;span style=&#34;color:#ed8796&#34;&gt;init&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; flower:Flower) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;           &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;.stringValue = flower.name
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;       }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;TODO:&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt; Codable shouldn&amp;#39;t be necessary but my Encoder requested it?&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   &lt;span style=&#34;color:#ed8796&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;Flower&lt;/span&gt;:&lt;span style=&#34;color:#91d7e3&#34;&gt;Hashable&lt;/span&gt;, Codable, CodingKeyRepresentable {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;       &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;name&lt;/span&gt;:&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;       &lt;span style=&#34;color:#ed8796&#34;&gt;init&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; name:&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;           &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;.name = name
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;       }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;       
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;       &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;codingKey&lt;/span&gt;: any CodingKey {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;           FlowerCodingKey.&lt;span style=&#34;color:#ed8796&#34;&gt;init&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;       }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;       
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;       &lt;span style=&#34;color:#ed8796&#34;&gt;init&lt;/span&gt;?&amp;lt;T&amp;gt;(codingKey: T) &lt;span style=&#34;color:#c6a0f6&#34;&gt;where&lt;/span&gt; T : CodingKey {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;           &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;.name = codingKey.stringValue
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;       }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;dictionaryB&lt;/span&gt;:&lt;span style=&#34;color:#91d7e3&#34;&gt;Dictionary&lt;/span&gt;&amp;lt;Flower,&lt;span style=&#34;color:#91d7e3&#34;&gt;Int&lt;/span&gt;&amp;gt; = [
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;       Flower(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;anemone&amp;#34;&lt;/span&gt;):&lt;span style=&#34;color:#f5a97f&#34;&gt;7&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;       Flower(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;freesia&amp;#34;&lt;/span&gt;):&lt;span style=&#34;color:#f5a97f&#34;&gt;6&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;       Flower(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;periwinkle&amp;#34;&lt;/span&gt;):&lt;span style=&#34;color:#f5a97f&#34;&gt;5&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   ]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//------------------ SingleValue&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;expectedA&lt;/span&gt; = &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;banana:2/kiwi:3/strawberry:1&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;expectedB&lt;/span&gt; = &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;anemone:7/freesia:6/periwinkle:5&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;encodedA&lt;/span&gt; = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; encoder.encode(dictionaryA)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;encodedB&lt;/span&gt; = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; encoder.encode(dictionaryB)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   XCTAssertEqual(expectedA, encodedA)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   XCTAssertEqual(expectedB, encodedB)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//--------- Keyed&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   &lt;span style=&#34;color:#ed8796&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;MiniWithDict&lt;/span&gt;:Encodable {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;       &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;first&lt;/span&gt;:&lt;span style=&#34;color:#91d7e3&#34;&gt;Dictionary&lt;/span&gt;&amp;lt;FruitKey,&lt;span style=&#34;color:#91d7e3&#34;&gt;UInt32&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;       &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;second&lt;/span&gt;:&lt;span style=&#34;color:#91d7e3&#34;&gt;Dictionary&lt;/span&gt;&amp;lt;Flower,&lt;span style=&#34;color:#91d7e3&#34;&gt;Int&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;miniToTest&lt;/span&gt; = MiniWithDict(&lt;span style=&#34;color:#91d7e3&#34;&gt;first&lt;/span&gt;: dictionaryA, second: dictionaryB)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;structExpected&lt;/span&gt; = &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;first.banana:2/first.kiwi:3/first.strawberry:1/second.anemone:7/second.freesia:6/second.periwinkle:5&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;encodedStruct&lt;/span&gt; = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; encoder.encode(miniToTest)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   XCTAssertEqual(structExpected, encodedStruct)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//--------- Unkeyed&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;dictArray&lt;/span&gt; = [dictionaryB, dictionaryB]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;arrayExpected&lt;/span&gt; = &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;0.anemone:7/0.freesia:6/0.periwinkle:5/1.anemone:7/1.freesia:6/1.periwinkle:5&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;encodedArray&lt;/span&gt; = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; encoder.encode(dictArray)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   XCTAssertEqual(arrayExpected, encodedArray)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;If one DOESN&amp;rsquo;T make the key &lt;code&gt;CodingKeyRepresentable&lt;/code&gt;, one ends up with a interlaced output that the decoder will have to know to stitch back together.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;testUnofficialKeyDictionary&lt;/span&gt;() &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   &lt;span style=&#34;color:#ed8796&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;MyKey&lt;/span&gt;:&lt;span style=&#34;color:#91d7e3&#34;&gt;Hashable&lt;/span&gt;, Codable {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;       &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;id&lt;/span&gt;:&lt;span style=&#34;color:#91d7e3&#34;&gt;UInt8&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;dictionaryA&lt;/span&gt;:&lt;span style=&#34;color:#91d7e3&#34;&gt;Dictionary&lt;/span&gt;&amp;lt;MyKey, &lt;span style=&#34;color:#91d7e3&#34;&gt;Int&lt;/span&gt;&amp;gt; = [
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;       MyKey(id: &lt;span style=&#34;color:#f5a97f&#34;&gt;127&lt;/span&gt;):&lt;span style=&#34;color:#f5a97f&#34;&gt;1&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;       MyKey(id: &lt;span style=&#34;color:#f5a97f&#34;&gt;126&lt;/span&gt;):&lt;span style=&#34;color:#f5a97f&#34;&gt;2&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;       MyKey(id: &lt;span style=&#34;color:#f5a97f&#34;&gt;125&lt;/span&gt;):&lt;span style=&#34;color:#f5a97f&#34;&gt;3&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   ]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//NOTE: This test will only intermittently pass&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//because dictionary order is arbitrary. &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//will be easier to test when can round trip with&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//decoder.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;expectedA&lt;/span&gt; = &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;0.id:125/&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;+&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                   &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;1:3/&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;+&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                   &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;2.id:126/&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;+&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                   &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;3:2/&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;+&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                   &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;4.id:127/&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;+&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                   &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;5:1&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;encodedA&lt;/span&gt; = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; encoder.encode(dictionaryA)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//.sorted(by: { $0.key &amp;lt; $1.key }) not Encodable&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   XCTAssertEqual(expectedA, encodedA)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;whats-the-deal-with-superencoder&#34;&gt;What&amp;rsquo;s the deal with superEncoder()?&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;.superEncoder()&lt;/code&gt; gets called when a subclass wants to use it&amp;rsquo;s parent class&amp;rsquo; encoder.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/apple/swift-evolution/blob/main/proposals/0166-swift-archival-serialization.md?plain=1#L880&#34;&gt;orig swift-evolution discussion&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/apple/swift-corelibs-foundation/blob/1dac1132d49b0ee4213ac89473019cae8a608b5c/Sources/Foundation/AttributedString/AttributedStringCodable.swift#L138&#34;&gt;example usage in AttributedString&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/apple/swift-distributed-actors/blob/c8af1b8d572526ab87211e0f615e4c40531cb5ce/Sources/DistributedCluster/ActorMessages.swift#L109&#34;&gt;example usage Distributed Actors&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I did a couple of tests using my own &lt;a href=&#34;https://github.com/carlynorama/CoderExplorer/blob/4d5cb306a623cce40076302fe7ca58ffefbde923/Tests/CoderExplorerTests/SimpleCoderTests.swift#L655&#34;&gt;class/subclass&lt;/a&gt; and one with &lt;a href=&#34;https://github.com/carlynorama/CoderExplorer/blob/4d5cb306a623cce40076302fe7ca58ffefbde923/Tests/CoderExplorerTests/SimpleCoderTests.swift#L706&#34;&gt;AttributedString&lt;/a&gt; which uses a lot of &lt;code&gt;.base64EncodedString()&lt;/code&gt; data. They&amp;rsquo;re not exactly super rigorous (why I&amp;rsquo;ve only added links), but it got me nominal coverage for:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;from Mine:  KeyedEncodingContainer.superEncoder()&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;from AttributedString: KeyedEncodingContainer.superEncoder(forKey key: Key)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;from AttributedString: UnkeyedEncodingContainer.superEncoder()&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Note about super and keys: &lt;a href=&#34;https://forums.swift.org/t/codable-with-references/13885/20&#34;&gt;https://forums.swift.org/t/codable-with-references/13885/20&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;the-remaining-fatalerrors&#34;&gt;The remaining fatalError()s&lt;/h2&gt;
&lt;p&gt;Nesting and unkeyed containers didn&amp;rsquo;t happen in either direction in my tests. Even where I expected them to. I could write my own custom objects that call them just for testing, but I&amp;rsquo;d rather wait until I understand who/what uses them in the wild for what.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;KeyedEncodingContainerProtocol.nestedUnkeyedContainer(forKey key: Key)&lt;/li&gt;
&lt;li&gt;UnkeyedEncodingContainer.nestedUnkeyedContainer()&lt;/li&gt;
&lt;li&gt;UnkeyedEncodingContainer.nestedContainer&lt;NestedKey&gt;(keyedBy keyType: NestedKey.Type)&lt;/li&gt;
&lt;li&gt;UnkeyedEncodingContainer.encodeNil&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;More research:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://forums.swift.org/search?q=UnkeyedEncodingContainer&#34;&gt;https://forums.swift.org/search?q=UnkeyedEncodingContainer&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/search?q=encoder.unkeyedContainer%28%29&amp;amp;type=code&#34;&gt;https://github.com/search?q=encoder.unkeyedContainer%28%29&amp;amp;type=code&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;confirmation they aren&amp;rsquo;t common: &lt;a href=&#34;https://forums.swift.org/t/codable-with-references/13885/17&#34;&gt;https://forums.swift.org/t/codable-with-references/13885/17&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;a-note-about-userinfo&#34;&gt;A note about userInfo&lt;/h2&gt;
&lt;p&gt;Most encoder implementations I&amp;rsquo;ve seen essentially ignore the protocol defined &lt;code&gt;userInfo&lt;/code&gt; dictionary, but the idea behind it is to pass down Encoder settings:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/apple/swift-evolution/blob/1b0b339bc3072a83b5a6a529ae405a0f076c7d5d/proposals/0166-swift-archival-serialization.md?plain=1#L831&#34;&gt;https://github.com/apple/swift-evolution/blob/1b0b339bc3072a83b5a6a529ae405a0f076c7d5d/proposals/0166-swift-archival-serialization.md?plain=1#L831&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://forums.swift.org/t/proper-way-to-structure-containers-in-new-coders/11712/5&#34;&gt;https://forums.swift.org/t/proper-way-to-structure-containers-in-new-coders/11712/5&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I&amp;rsquo;ve found at least one thing that uses it that way though:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://forums.swift.org/t/codable-items-with-identity/60726/3&#34;&gt;https://forums.swift.org/t/codable-items-with-identity/60726/3&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;More research:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/search?q=encoder.userInfo+language%3ASwift&amp;amp;type=code&amp;amp;l=Swift&#34;&gt;https://github.com/search?q=encoder.userInfo+language%3ASwift&amp;amp;type=code&amp;amp;l=Swift&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I&amp;rsquo;m curious if it gets used with &lt;a href=&#34;https://developer.apple.com/documentation/foundation/codablewithconfiguration&#34;&gt;&lt;code&gt;CodableWithConfiguration&lt;/code&gt;&lt;/a&gt; implementations?&lt;/p&gt;
&lt;h2 id=&#34;codablewithconfiguration&#34;&gt;CodableWithConfiguration&lt;/h2&gt;
&lt;p&gt;I have not implemented any custom handlers for things that are &lt;a href=&#34;https://developer.apple.com/documentation/foundation/codablewithconfiguration&#34;&gt;&lt;code&gt;CodableWithConfiguration&lt;/code&gt;&lt;/a&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://www.andyibanez.com/posts/the-mysterious-codablewithconfiguration-protocol/&#34;&gt;https://www.andyibanez.com/posts/the-mysterious-codablewithconfiguration-protocol/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;summary&#34;&gt;Summary&lt;/h2&gt;
&lt;p&gt;Encoders. Not so fiddly if one can be ruthless in vetting the input. Interminable to write if trying to be general purpose.&lt;/p&gt;
&lt;p&gt;Next post will be the &lt;code&gt;Decoder&lt;/code&gt; for this &lt;code&gt;SimpleCoder&lt;/code&gt; which may cause it to be entirely rewritten!&lt;/p&gt;
</description>
    </item>
    
    
    
    <item>
      <title>How do custom Encoder&#39;s work?</title>
      <link>https://whynotestflight.com/excuses/how-do-custom-encoders-work/</link>
      <pubDate>Wed, 06 Mar 2024 00:00:00 +0000</pubDate>
      
      <guid>https://whynotestflight.com/excuses/how-do-custom-encoders-work/</guid>
      <description>&lt;p&gt;So if I&amp;rsquo;m going to save the Line data as a file in the AppGroup storage area, what&amp;rsquo;s going to be in that file? The current bespoke String-&amp;gt;Line/Line-&amp;gt;String transformations have a lot of vulnerabilities.  Given that we&amp;rsquo;re also working with JavaScript JSON would make a lot of sense. I quickly added JSON to the &lt;a href=&#34;https://github.com/carlynorama/SimplePersist&#34;&gt;SimplePersist&lt;/a&gt; library, but realized that default JSONEncoder encodes whole objects only. This works well if transmitting the JSON over a network with the idea of checking that the whole object was received.  It&amp;rsquo;s less ideal for data storage in a file where appending new items to the end without loading all of the data into memory would be useful. For the current very small amount of text data that would actually be fine, but I&amp;rsquo;ve been meaning to learn how to write custom Encoders and Decoders for awhile now. Here&amp;rsquo;s the excuse!&lt;/p&gt;
&lt;p&gt;I used a handful of examples to guide my process:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Solid Tutorial: objc.io Swift Talk # 348: &lt;a href=&#34;https://talk.objc.io/episodes/S01E348-routing-with-codable-encoding&#34;&gt;Routing with Codable – Encoding&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;StackOverflow 45169254: &lt;a href=&#34;https://stackoverflow.com/questions/45169254/custom-swift-encoder-decoder-for-the-strings-resource-format&#34;&gt;Custom Swift Encoder/Decoder for the Strings Resource Format&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/apple/swift-corelibs-foundation/blob/release/5.10/Sources/Foundation/JSONEncoder.swift&#34;&gt;JSONEncoder from 5.10&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/apple/swift-foundation/blob/main/Sources/FoundationEssentials/JSON/JSONEncoder.swift&#34;&gt;JSONENcoder in FoundationEssentials&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/apple/swift-openapi-runtime/tree/release/0.2.x/Sources/OpenAPIRuntime/URICoder&#34;&gt;Swift-OpenAPI URI Encoder&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/apple/swift-http-structured-headers/blob/main/Sources/StructuredFieldValues/&#34;&gt;StructuredFieldValues from Swift HTTP Structured Headers&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/apple/swift-package-manager/blob/a5f9b6cf7ceeea13b7db828b5eece2ca9e0df445/Sources/Commands/Utilities/PlainTextEncoder.swift&#34;&gt;Swift Package Manager PlainTextEncoder&lt;/a&gt; Encoder only. Output direct to an OutputStream.&lt;/li&gt;
&lt;li&gt;ETA: &lt;a href=&#34;https://github.com/CoreOffice/XMLCoder/blob/main/Sources/XMLCoder/&#34;&gt;CoreOffice/XMLCoder&lt;/a&gt; (see epilogue)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The &lt;code&gt;Encodable&lt;/code&gt; side of the &lt;code&gt;Codable&lt;/code&gt; ecosystem essentially boils down to &lt;code&gt;Encodable&lt;/code&gt; conforming items have the potential to offer up a &amp;lt;CodingKey, Any&amp;gt; dictionary out of themselves and the intrepid Swift developer can then use the hooks provided by an &lt;code&gt;Encoder&lt;/code&gt; conforming type to place that information in a data structure of their own making. Depending on the nature of that data structure an additional &lt;a href=&#34;https://en.wikipedia.org/wiki/Serialization&#34;&gt;serialization&lt;/a&gt; step to spin the information into the desired final output format may be required.&lt;/p&gt;
&lt;p&gt;Two different approaches emerge at this point. The first and simpler does most of the serialization work in the first pass of the encoder so the &amp;ldquo;data structure&amp;rdquo; is a thin veil over the desired final output. This approach gets used when the input data will be simple or the the Encoder itself doesn&amp;rsquo;t allow for much customization. The encoder can just return it&amp;rsquo;s data store practically as is when done. It could look something like:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//-------------------------------- PSUEDO CODE ---------------------------------&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;PublicEncoderType&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;encode&lt;/span&gt;(value:Encodable) -&amp;gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        encoder = _PrivateEncoderType(data:myData())
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        value.encode(to: encoder)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; encoder.value
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//Sometimes inside the above class, sometimes not.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;_PrivateEncoderType&lt;/span&gt;:Encoder {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;data&lt;/span&gt; = MyDataType
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;value&lt;/span&gt;:&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        data.storage
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//...other things&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//Sometimes inside one of the above classes, sometimes not.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;MyDataType&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;storage&lt;/span&gt;:&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;append&lt;/span&gt;&amp;lt;T&amp;gt;(value:T, forKey key:CodingKey?) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        storage.append(delimiter)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;key&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            storage.append(key.stringValue)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            storage.append(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;:&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        storage.append(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;value&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//etc&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;img src=&#34;Encoders_simplified.png&#34; alt=&#34;Chart of a simplified encoder&#34;&gt;&lt;/p&gt;
&lt;p&gt;This is along the lines of what&amp;rsquo;s seen in the &lt;a href=&#34;https://stackoverflow.com/questions/45169254/custom-swift-encoder-decoder-for-the-strings-resource-format&#34;&gt;StackOverflow example&lt;/a&gt; and the &lt;a href=&#34;https://talk.objc.io/episodes/S01E348-routing-with-codable-encoding&#34;&gt;SwiftTalk example&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;In that &lt;a href=&#34;https://stackoverflow.com/questions/45169254/custom-swift-encoder-decoder-for-the-strings-resource-format&#34;&gt;StackOverflow example&lt;/a&gt; Paulo Mattos embeds the storage type into the Encoder. It handles its own updating with an encode function.  He does not show a Decoder.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;fileprivate &lt;span style=&#34;color:#ed8796&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;StringsEncoding&lt;/span&gt;: Encoder {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    fileprivate &lt;span style=&#34;color:#c6a0f6&#34;&gt;final&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;Data&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;private&lt;/span&gt;(&lt;span style=&#34;color:#c6a0f6&#34;&gt;set&lt;/span&gt;) &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;strings&lt;/span&gt;: [&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;: &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;] = [:]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;encode&lt;/span&gt;(key codingKey: [CodingKey], value: &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;key&lt;/span&gt; = codingKey.&lt;span style=&#34;color:#91d7e3&#34;&gt;map&lt;/span&gt; { &lt;span style=&#34;color:#f4dbd6&#34;&gt;$0&lt;/span&gt;.stringValue }.joined(separator: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;.&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            strings[key] = value
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;In the &lt;a href=&#34;https://talk.objc.io/episodes/S01E348-routing-with-codable-encoding&#34;&gt;SwiftTalk example&lt;/a&gt; the storage type stands alone as it gets used for both encoding and decoding. It&amp;rsquo;s just a dumb storage box being used for its reference-typeyness. Other things know how to update it.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;RouteEncoder&lt;/span&gt;: Encoder {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;components&lt;/span&gt;: Box&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;lt;&lt;/span&gt;[&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;]&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;RouteDecoder&lt;/span&gt;:Decoder {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;components&lt;/span&gt;: Box&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;lt;&lt;/span&gt;[&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;]&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;     &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;final&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;Box&lt;/span&gt;&amp;lt;Value&amp;gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;value&lt;/span&gt;: Value
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;init&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; value: Value) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;.value = value
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The second more complex approach would be to create some kind of &lt;code&gt;CustomDataNode&lt;/code&gt; like structure that can handle insertions into a nested hierarchy which may or may not transform any of the data types.  This works better for more complex data or generalized implementations that potentially need more runtime customization. A separate serialization service also gets created that can take in an instance of the &lt;code&gt;CustomDataNode&lt;/code&gt; type and produce the desired final output type. This could look something like:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//-------------------------------- PSUEDO CODE ---------------------------------&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;PublicEncoderType&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;encode&lt;/span&gt;(value:Encodable) -&amp;gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;encoder&lt;/span&gt; = _PrivateEncoderType()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;encodedValue&lt;/span&gt; = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; encoder.encodeAsDataNode(value)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//sometimes the serializer is passed into the encoder. &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;serializer&lt;/span&gt; = (some SerializerProtocol)()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; serializer.createString(encodedValue) 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//Sometimes inside the above class, sometimes not.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;_PrivateEncoderType&lt;/span&gt;:Encoder {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;data&lt;/span&gt; = MyDataNode
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;encodeAsDataNode&lt;/span&gt;(value:Encodable) -&amp;gt; MyDataNode {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//Serious fanciness ensues to update data.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; data
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//...other things&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//Sometimes inside one of the above classes, sometimes not.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;enum&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;MyDataNode&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;case&lt;/span&gt; value(&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;internal&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;case&lt;/span&gt; array([value])
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;internal&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;case&lt;/span&gt; object([&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;:value])
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;protocol&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;SerializerProtocol&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//fanciness to get the data -&amp;gt; the desired output.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;createString&lt;/span&gt;(MyDataNode) -&amp;gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p id=&#34;handle-dates&#34;&gt;With the explicitly two step process some harder decisions have to be made about what is &amp;ldquo;Encoding&amp;rdquo; and what is &amp;ldquo;Serialization.&amp;rdquo; Lets look at the example of a &lt;code&gt;Date&lt;/code&gt;.  If the Encoder will override a Codable value&amp;rsquo;s default transformation, it has to catch it somewhere.&lt;/p&gt;
&lt;p&gt;In the &lt;a href=&#34;https://github.com/apple/swift-openapi-runtime/tree/release/0.2.x/Sources/OpenAPIRuntime/URICoder&#34;&gt;URIEncoder&lt;/a&gt; a &lt;code&gt;Date&lt;/code&gt; gets held in the &lt;a href=&#34;https://github.com/apple/swift-openapi-runtime/blob/76951d77a0609599d2dc233e7e40808a74767c6a/Sources/OpenAPIRuntime/URICoder/Common/URIEncodedNode.swift&#34;&gt;&lt;code&gt;URIEncodedNode&lt;/code&gt;&lt;/a&gt; as a &lt;code&gt;Date&lt;/code&gt;. A [&lt;code&gt;URISerializer&lt;/code&gt;][&lt;a href=&#34;https://github.com/apple/swift-openapi-runtime/blob/76951d77a0609599d2dc233e7e40808a74767c6a/Sources/OpenAPIRuntime/URICoder/Serialization/URISerializer.swift#L18&#34;&gt;serializer&lt;/a&gt;] instance, configured with a &lt;a href=&#34;https://github.com/apple/swift-openapi-runtime/blob/76951d77a0609599d2dc233e7e40808a74767c6a/Sources/OpenAPIRuntime/URICoder/Common/URICoderConfiguration.swift#L51&#34;&gt;DateTranscoder&lt;/a&gt;, gets passed to the &lt;code&gt;Encoder&lt;/code&gt; on initialization. This serializer then handles all the &lt;code&gt;-&amp;gt; String&lt;/code&gt; behaviors. The &lt;code&gt;URIEncodedNode&lt;/code&gt; catches the &lt;code&gt;Date&lt;/code&gt; before it can be stringified by its own Encodableyness right in the main &lt;a href=&#34;https://github.com/apple/swift-openapi-runtime/blob/76951d77a0609599d2dc233e7e40808a74767c6a/Sources/OpenAPIRuntime/URICoder/Encoding/URIValueToNodeEncoder.swift#L71&#34;&gt;&lt;code&gt;encodeValue(some Encodable)&lt;/code&gt;&lt;/a&gt; function.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;Encoders_URI.png&#34; alt=&#34;Chart of the URIEncoder&#34;&gt;&lt;/p&gt;
&lt;p&gt;In both the JSONEncoders, a &lt;code&gt;Date&lt;/code&gt; gets turned into a &lt;code&gt;String&lt;/code&gt; by the &lt;code&gt;Encoder&lt;/code&gt; in a function that uses the &lt;a href=&#34;https://github.com/search?q=org%3AApple%20DateEncodingStrategy&amp;amp;type=code&#34;&gt;&lt;code&gt;DateEncodingStrategy&lt;/code&gt;&lt;/a&gt; to determine the format before it even hits the &lt;a href=&#34;https://github.com/apple/swift-corelibs-foundation/blob/19e5eb0edebf67f69908f6ef0e9c0ad934848c82/Sources/Foundation/JSONEncoder.swift#L246&#34;&gt;&lt;code&gt;JSONFuture&lt;/code&gt;&lt;/a&gt;/&lt;a href=&#34;https://github.com/apple/swift-foundation/blob/ac5770ee24c9b57370ad3dcc3a9715fae586f603/Sources/FoundationEssentials/JSON/JSONEncoder.swift#L508&#34;&gt;&lt;code&gt;JSONReference&lt;/code&gt;&lt;/a&gt; data storage types of the 5.10 version and the FoundationEssential version respectively. The serializer in the JSONEncoders is called a writer. In the 5.10 version it&amp;rsquo;s &lt;a href=&#34;https://github.com/apple/swift-corelibs-foundation/blob/778dde90ff7cf63f05634c3df6b0788c89249770/Sources/Foundation/JSONEncoder.swift#L970&#34;&gt;attached as extension&lt;/a&gt; to  backing storage type of a &lt;code&gt;JSONFuture&lt;/code&gt;, a &lt;a href=&#34;https://github.com/apple/swift-corelibs-foundation/blob/778dde90ff7cf63f05634c3df6b0788c89249770/Sources/Foundation/JSONSerialization.swift#L629&#34;&gt;JSONValue&lt;/a&gt;. In the FoundationEssentials version it&amp;rsquo;s a standalone &lt;a href=&#34;https://github.com/apple/swift-foundation/blob/ac5770ee24c9b57370ad3dcc3a9715fae586f603/Sources/FoundationEssentials/JSON/JSONWriter.swift#L124&#34;&gt;JSONWriter&lt;/a&gt;. Both writers take configuration values for other things, but the &lt;em&gt;date strategy&lt;/em&gt; belongs to the &lt;code&gt;Encoders&lt;/code&gt; not the &lt;code&gt;Writers&lt;/code&gt;.  The function that intercepts the &lt;code&gt;Date&lt;/code&gt; lives in a &lt;code&gt;_SpecialTreatmentEncoder&lt;/code&gt; protocol for the 5.10 &lt;code&gt;JSONEncoder&lt;/code&gt;. That protocol gets applied to just about everything. In the FoundationEssentials version those &amp;ldquo;wrap&amp;rdquo; functions live in the &lt;code&gt;Encoder&lt;/code&gt; implementation which gets passed around.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;Encoders_JSON_5_10.png&#34; alt=&#34;Chart of the JSONEncoder in the 5.10 release&#34;&gt;
&lt;img src=&#34;Encoders_JSON_FE.png&#34; alt=&#34;Chart of the JSONEncoder in the FoundationEssentials&#34;&gt;&lt;/p&gt;
&lt;p&gt;The http-structured-headers &lt;code&gt;StructuredFieldValue&lt;/code&gt; approach instead restrains the inputs. It requires all values submitted to the &lt;a href=&#34;https://github.com/apple/swift-http-structured-headers/blob/2e8ae2a7661555834caadd2ca6744aab69cfc1b4/Sources/StructuredFieldValues/Encoder/StructuredFieldValueEncoder.swift#L47&#34;&gt;top level public encode function&lt;/a&gt; to &lt;a href=&#34;https://github.com/apple/swift-http-structured-headers/blob/2e8ae2a7661555834caadd2ca6744aab69cfc1b4/Sources/StructuredFieldValues/StructuredFieldValue.swift#L20&#34;&gt;conform to a protocol&lt;/a&gt; with the single requirement of an enum value that can tell the Encoder if it&amp;rsquo;s a single value item, array or object. To shorten what&amp;rsquo;s actually a longer story, the backing storage won&amp;rsquo;t even accept a &lt;code&gt;Date&lt;/code&gt;. An allowed &lt;a href=&#34;https://github.com/apple/swift-http-structured-headers/blob/2e8ae2a7661555834caadd2ca6744aab69cfc1b4/Sources/RawStructuredFieldValues/ComponentTypes.swift#L35&#34;&gt;&lt;code&gt;BareItem&lt;/code&gt;&lt;/a&gt; must already be a &lt;code&gt;Bool&lt;/code&gt;, &lt;code&gt;Int&lt;/code&gt; or predigested into a specialized String. A &lt;code&gt;Date&lt;/code&gt; couldn&amp;rsquo;t even get that far without throwing an error.  Additionally, since this package has a very constrained output type it provides a single lightweight non-customizable serializer struct that gets initialized on demand in several places.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;Encoders_SFV.png&#34; alt=&#34;Chart of the StructuredFieldView Encoder&#34;&gt;&lt;/p&gt;
&lt;h2 id=&#34;encoding-containers&#34;&gt;Encoding Containers&lt;/h2&gt;
&lt;p&gt;So what entities even make the calls to update the data store? Lets pull out the &lt;a href=&#34;https://github.com/apple/swift/blob/48e65c6f8ca1a2a902df40c51173fc603b1611e2/stdlib/public/core/Codable.swift#L100C1-L139C1&#34;&gt;Encoder protocol&lt;/a&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;protocol&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;Encoder&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;/// The path of coding keys taken to get to this point in encoding.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;codingPath&lt;/span&gt;: [any CodingKey] { &lt;span style=&#34;color:#c6a0f6&#34;&gt;get&lt;/span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;/// Any contextual information set by the user for encoding.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;userInfo&lt;/span&gt;: [CodingUserInfoKey: &lt;span style=&#34;color:#91d7e3&#34;&gt;Any&lt;/span&gt;] { &lt;span style=&#34;color:#c6a0f6&#34;&gt;get&lt;/span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;/// Returns an encoding container appropriate for holding multiple values&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;/// keyed by the given key type.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;/// ... (e.g. Structs, Classes, Dicts)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;container&lt;/span&gt;&amp;lt;Key&amp;gt;(keyedBy type: Key.&lt;span style=&#34;color:#c6a0f6&#34;&gt;Type&lt;/span&gt;) -&amp;gt; KeyedEncodingContainer&amp;lt;Key&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;/// Returns an encoding container appropriate for holding multiple unkeyed&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;/// values.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;///... (e.g. Arrays)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;unkeyedContainer&lt;/span&gt;() -&amp;gt; any UnkeyedEncodingContainer
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;/// Returns an encoding container appropriate for holding a single primitive&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;/// value.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;///... (Bare primitives)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;singleValueContainer&lt;/span&gt;() -&amp;gt; any SingleValueEncodingContainer
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The &lt;code&gt;container&lt;/code&gt; function returns a concrete &lt;a href=&#34;https://github.com/apple/swift/blob/48e65c6f8ca1a2a902df40c51173fc603b1611e2/stdlib/public/core/Codable.swift#L497&#34;&gt;&lt;code&gt;KeyedEncodingContainer&amp;lt;Key&amp;gt;&lt;/code&gt;&lt;/a&gt; whose initializer wraps the developer&amp;rsquo;s own implementation of the KeyedEncodingContainerProtocol. The other two allow for just returning a protocol conforming type directly.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/search?q=org%3Aapple%20KeyedEncodingContainerProtocol&amp;amp;type=code&#34;&gt;KeyedEncodingContainerProtocol&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/search?q=org%3Aapple%20UnkeyedEncodingContainer&amp;amp;type=code&#34;&gt;UnkeyedEncodingContainer&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/search?q=org%3Aapple+SingleValueEncodingContainer&amp;amp;type=code&#34;&gt;SingleValueEncodingContainer&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;(see &lt;a href=&#34;https://github.com/apple/swift/blob/5a42260f6316ab38c21d7acf56f3728ff3718b80/stdlib/public/core/Codable.swift&#34;&gt;Codable&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In the diagrams above they&amp;rsquo;re the purple boxes on the bottom.&lt;/p&gt;
&lt;p&gt;Sometimes a developer&amp;rsquo;s implementation of these protocols&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;extends an &lt;code&gt;Encoder&lt;/code&gt; directly&lt;/li&gt;
&lt;li&gt;gets passed an &lt;code&gt;Encoder&lt;/code&gt; to use&lt;/li&gt;
&lt;li&gt;gets passed a reference to the data storage object that the active &lt;code&gt;Encoder&lt;/code&gt; is using.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;All of these approaches work to enable these &amp;ldquo;Encoding Containers&amp;rdquo;  to squirrel the submitted values into the appropriate data store. Note that something somewhere has to be a reference type so it can persist through multiple passes of the encoding process.&lt;/p&gt;
&lt;p&gt;The encoding containers route the encoding process via nearly identical lists of functions which help the developer make sure they have thought of everything a generic &lt;code&gt;Encodable&lt;/code&gt; item could throw at it. Examples include:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;mutating func encodeNil() throws&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;mutating func encode(_ value: Bool) throws&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;mutating func encodeIfPresent(_ value: Bool?, forKey key: Key) throws&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;mutating func encode(_ value: Int64) throws&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;mutating func encode&amp;lt;T: Encodable&amp;gt;(_ value: T) throws&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;etc.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If a custom &lt;code&gt;Encoder&lt;/code&gt; limits the types of values it can take in, it&amp;rsquo;s possible to get away with only adding valid implementations to a subset of the functions, but most of them still have to be there.&lt;/p&gt;
&lt;h2 id=&#34;handling-codingkeys&#34;&gt;Handling CodingKeys&lt;/h2&gt;
&lt;p&gt;Developers also have to decide where and when &lt;code&gt;CodingKey&lt;/code&gt;s get handled. The documentation simply states that a &lt;code&gt;CodingKey&lt;/code&gt; is  &amp;ldquo;a type that can be used as a key for encoding and decoding&amp;rdquo;. I did not find that particularly illuminating. Essentially, the CodingKey can store the name of the struct or parameter or whatever custom thing the person conforming their struct to Codable wanted it to be (&lt;a href=&#34;https://www.hackingwithswift.com/quick-start/swiftdata/how-to-make-swiftdata-models-conform-to-codable&#34;&gt;example&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;Conformance to &lt;code&gt;Encoder&lt;/code&gt; and all of the encoding containers requires making a &lt;code&gt;codingPath&lt;/code&gt; available, describable as a &lt;code&gt;NavigationPath&lt;/code&gt; like array of &lt;code&gt;CodingKey&lt;/code&gt;s.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;codingPath&lt;/span&gt;: [any CodingKey] { &lt;span style=&#34;color:#c6a0f6&#34;&gt;get&lt;/span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Many implementations of encoding containers either set their codingPath to an empty array or set it to pull from a wrapped concrete &lt;code&gt;Encoder&lt;/code&gt; directly. The objc.io example didn&amp;rsquo;t care about keys at all. It was making a URL based on values only. Some implementations leave it empty because the serializer only needs to know the key for the current level. Appending values to the path only becomes important if the serializer needs the full context to create appropriately formatted output along the lines of the StackOverflow example.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;StructA.StructB.StructC:43&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;What even is the &lt;code&gt;CodingKey&lt;/code&gt; type? It&amp;rsquo;s just a protocol that&amp;rsquo;s pretty darn easy to conform to:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//minimum viable CodingKey&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;internal&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;MySpecialKey&lt;/span&gt;: CodingKey {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;stringValue&lt;/span&gt;: &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;init&lt;/span&gt;?(stringValue: &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;lt;&lt;/span&gt;#code#&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;intValue&lt;/span&gt;: &lt;span style=&#34;color:#91d7e3&#34;&gt;Int&lt;/span&gt;?
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;init&lt;/span&gt;?(intValue: &lt;span style=&#34;color:#91d7e3&#34;&gt;Int&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;lt;&lt;/span&gt;#code#&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;However, just like with values, something has to do the transformation of the &lt;code&gt;CodingKey&lt;/code&gt; into the Output type. The 5.10 JSONEncoder and some of the simpler types store the encoded information with the keys &lt;a href=&#34;https://github.com/apple/swift-corelibs-foundation/blob/778dde90ff7cf63f05634c3df6b0788c89249770/Sources/Foundation/JSONEncoder.swift#L621&#34;&gt;already turned into strings&lt;/a&gt; based on a strategy &lt;a href=&#34;https://github.com/apple/swift-corelibs-foundation/blob/778dde90ff7cf63f05634c3df6b0788c89249770/Sources/Foundation/JSONEncoder.swift#L205&#34;&gt;owned by the Encoder&lt;/a&gt; not the Writer.&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;    public enum KeyEncodingStrategy : Sendable {
        case useDefaultKeys
        case convertToSnakeCase
        case custom(@Sendable (_ codingPath: [CodingKey]) -&amp;gt; CodingKey)
    }
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;In the &lt;em&gt;container&lt;/em&gt;  (_JSONKeyedEncodingContainer):&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;    private func _converted(_ key: CodingKey) -&amp;gt; String {
        switch encoder.options.keyEncodingStrategy {
        case .useDefaultKeys:
            return key.stringValue
        case .convertToSnakeCase:
            let newKeyString = JSONEncoder.KeyEncodingStrategy._convertToSnakeCase(key.stringValue)
            return newKeyString
        case .custom(let converter):
            return converter(codingPathNode.path(with: key)).stringValue
        }
    }
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Some of the more recently written encoders have a wrapping type which pairs the encoded value to &lt;code&gt;CodingKey&lt;/code&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;the &lt;a href=&#34;https://github.com/search?q=org%3AApple%20CodingStackEntry&amp;amp;type=code&#34;&gt;CodingStackEntry&lt;/a&gt; of StructuredFieldValue and URIEncoder&lt;/li&gt;
&lt;li&gt;the &lt;a href=&#34;https://github.com/apple/swift-foundation/blob/ac5770ee24c9b57370ad3dcc3a9715fae586f603/Sources/FoundationEssentials/JSON/JSONEncoder.swift#L1306&#34;&gt;_JSONCodingPathNode&lt;/a&gt; of FoundationEssentials.&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;internal&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;enum&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;_JSONCodingPathNode&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;case&lt;/span&gt; root
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;indirect&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;case&lt;/span&gt; node(CodingKey, _JSONCodingPathNode)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;path&lt;/span&gt; : [CodingKey] {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;switch&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;case&lt;/span&gt; .root:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; []
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;case&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; .node(key, parent):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; parent.path &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;+&lt;/span&gt; [key]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//..more&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;final&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;URIValueToNodeEncoder&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;CodingStackEntry&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;key&lt;/span&gt;: URICoderCodingKey
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;storage&lt;/span&gt;: URIEncodedNode
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;///...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;private&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;_codingPath&lt;/span&gt;: [CodingStackEntry]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;currentStackEntry&lt;/span&gt;: CodingStackEntry
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;init&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;._codingPath = []
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;.currentStackEntry = CodingStackEntry(key: .&lt;span style=&#34;color:#ed8796&#34;&gt;init&lt;/span&gt;(stringValue: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;), storage: .unset)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;extension&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;URIValueToNodeEncoder&lt;/span&gt;: Encoder {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;codingPath&lt;/span&gt;: [any CodingKey] {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        (_codingPath.&lt;span style=&#34;color:#91d7e3&#34;&gt;dropFirst&lt;/span&gt;().&lt;span style=&#34;color:#91d7e3&#34;&gt;map&lt;/span&gt;(&lt;span style=&#34;color:#ed8796&#34;&gt;\&lt;/span&gt;.key) &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;+&lt;/span&gt; [currentStackEntry.key]).&lt;span style=&#34;color:#91d7e3&#34;&gt;map&lt;/span&gt; { &lt;span style=&#34;color:#f4dbd6&#34;&gt;$0&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;as&lt;/span&gt; any CodingKey }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;These actually aren&amp;rsquo;t really for serializing the key values. They get used for handling nested encoders without creating new encoders.  These three &lt;code&gt;Encoder&lt;/code&gt; types also have &lt;code&gt;push&lt;/code&gt; and &lt;code&gt;pop&lt;/code&gt; functions to change their current encoding depth. The &lt;code&gt;CodingKey&lt;/code&gt;s are still already stringified and sanitized before they&amp;rsquo;re inserted into the stored data objects and the serializer uses those values. This NodeType seems to be more about organizing nested containers than participating in the encoded key creation.&lt;/p&gt;
&lt;h2 id=&#34;summary&#34;&gt;Summary&lt;/h2&gt;
&lt;p&gt;Encoders can be difficult to get started with because of the amount of flexibility they offer in terms of the approaches they&amp;rsquo;d support. Copying a few examples to understand how they work helped me a lot. Next post will cover a couple of implementation examples.&lt;/p&gt;
&lt;h2 id=&#34;epilogue---xmlcoder&#34;&gt;Epilogue - XMLCoder&lt;/h2&gt;
&lt;p&gt;One more Encoder to add to the stash. &lt;a href=&#34;https://github.com/CoreOffice/XMLCoder/blob/main/Sources/XMLCoder/&#34;&gt;CoreOffice/XMLCoder&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;It uses a protocol instead of an enum to wrap all the possible values up in a format the serializer will know how to digest. A &lt;code&gt;Date&lt;/code&gt; in this case would get caught and wrapped into a &lt;a href=&#34;https://github.com/CoreOffice/XMLCoder/blob/efda1cc8e0a97d198b6d16d53ff73751bd93f801/Sources/XMLCoder/Auxiliaries/Box/DateBox.swift&#34;&gt;&lt;code&gt;DateBox&lt;/code&gt;&lt;/a&gt; when it hit an &lt;code&gt;encoder.box(value)&lt;/code&gt; step. That &lt;code&gt;DateBox&lt;/code&gt; would likely be wrapped inside a &lt;code&gt;SharedBox&lt;/code&gt; (the class type) and be placed inside the encoder&amp;rsquo;s storage array.&lt;/p&gt;
&lt;p&gt;The &lt;a href=&#34;https://github.com/CoreOffice/XMLCoder/blob/efda1cc8e0a97d198b6d16d53ff73751bd93f801/Sources/XMLCoder/Auxiliaries/XMLCoderElement.swift#L11&#34;&gt;&lt;code&gt;XMLCoderElement&lt;/code&gt;&lt;/a&gt; &lt;a href=&#34;https://github.com/CoreOffice/XMLCoder/blob/efda1cc8e0a97d198b6d16d53ff73751bd93f801/Sources/XMLCoder/Auxiliaries/XMLCoderElement.swift#L341&#34;&gt;initializers&lt;/a&gt; know how to unbox Box types and turn them into the correct &lt;code&gt;XMLCoderElement&lt;/code&gt; configuration.&lt;/p&gt;
&lt;p&gt;The &lt;a href=&#34;https://github.com/CoreOffice/XMLCoder/blob/efda1cc8e0a97d198b6d16d53ff73751bd93f801/Sources/XMLCoder/Auxiliaries/XMLCoderElement.swift#L11&#34;&gt;&lt;code&gt;XMLCoderElement&lt;/code&gt;&lt;/a&gt; felt like both serializer and storage so I made it a bit more orange than the other Serializers.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;Encoders_XML.png&#34; alt=&#34;Diagram of XMLEncoder from CoreOffice&#34;&gt;&lt;/p&gt;
</description>
    </item>
    
    
    
    <item>
      <title>How to do some basic file handling?</title>
      <link>https://whynotestflight.com/excuses/how-to-do-some-basic-file-handling/</link>
      <pubDate>Thu, 22 Feb 2024 00:00:00 +0000</pubDate>
      
      <guid>https://whynotestflight.com/excuses/how-to-do-some-basic-file-handling/</guid>
      <description>&lt;p&gt;Related Repo: &lt;a href=&#34;https://github.com/carlynorama/SimplePersist&#34;&gt;https://github.com/carlynorama/SimplePersist&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Great [Performance Comparison by Tera on the Swift Forum] (&lt;a href=&#34;https://forums.swift.org/t/what-is-the-best-way-to-work-with-the-file-system/71020/18&#34;&gt;https://forums.swift.org/t/what-is-the-best-way-to-work-with-the-file-system/71020/18&lt;/a&gt;)&lt;/p&gt;
&lt;p&gt;Continuing with the Lines App, what&amp;rsquo;s the best way to store the saved text so both Lines and LineGrabber can use it? At the end of the post I&amp;rsquo;ve dumped a checklist of some of what I consider when picking a data storage solution. Some of it&amp;rsquo;s technical. Some of it is about the working environment of people who will interact with the data. It&amp;rsquo;s a bit overkill for this stage of the Lines app but it&amp;rsquo;s in the back of my head. Right now the Lines data gets loaded fresh from a file, and we&amp;rsquo;re going to stick with loading it back to a file.&lt;/p&gt;
&lt;p&gt;That brings up some interesting questions about where to save that file. Right now it&amp;rsquo;s in the Lines bundle, but what if it was saved to the App group? That way both processes (Lines and LineGrabber) could interact with it?&lt;/p&gt;
&lt;p&gt;That kind of multi-process file access can be very difficult to get right. What happens if one process is ready to write while the other is reading? &lt;a href=&#34;https://developer.apple.com/videos/play/wwdc2021/10133&#34;&gt;Actors&lt;/a&gt; help mitigate that issue within a single app&amp;rsquo;s boundaries, but at least historically file systems have &lt;a href=&#34;https://en.wikipedia.org/wiki/File_locking&#34;&gt;used Locks&lt;/a&gt;. One help, this data storage file won&amp;rsquo;t be willny nilly out in the file system subject to the whims of any process that wanders past. It will live in a sandbox which offers some protections.&lt;/p&gt;
&lt;h3 id=&#34;references&#34;&gt;References&lt;/h3&gt;
&lt;p&gt;Handy links I don&amp;rsquo;t want to loose track of&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Article on how to have &lt;a href=&#34;https://people.cs.ksu.edu/~danielwang/Investigation/RTOS/article_913_1.pdf&#34;&gt;two processes share a file in C&lt;/a&gt; for contrast.&lt;/li&gt;
&lt;li&gt;DocC&amp;rsquo;s &lt;a href=&#34;https://github.com/apple/swift-docc/blob/a0644adfbe854573d2a2a180be396d9a835460c8/Sources/SwiftDocCUtilities/Utility/DirectoryMonitor.swift#L153C45-L153C54&#34;&gt;Document Monitor&lt;/a&gt;. Pretty clever.&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://wadetregaskis.com/creating-temporary-files-safely-in-mac-apps/&#34;&gt;C &amp;amp; Swift tmp file&lt;/a&gt; article mentioned below:&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://www.unix.com/man-page/mojave/2/open/&#34;&gt;https://www.unix.com/man-page/mojave/2/open/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;whats-in-the-tin&#34;&gt;What&amp;rsquo;s in the Tin&lt;/h2&gt;
&lt;p&gt;Given I&amp;rsquo;d prefer not to roll my own file system interactions, I spent some time looking at what Swift can already do.&lt;/p&gt;
&lt;p&gt;I highly recommend this article by Wade Tregaskis who goes over &lt;a href=&#34;https://wadetregaskis.com/creating-temporary-files-safely-in-mac-apps/&#34;&gt;creating tmp files with both Swift and C API&lt;/a&gt;&amp;rsquo;s. Very handy.&lt;/p&gt;
&lt;p&gt;Some criteria: Whatever I write will likely be in the form of a library and I &lt;em&gt;prefer&lt;/em&gt; Library code to run everywhere Swift does. So my preference will be to use the highest level library that exists since I don&amp;rsquo;t know &lt;em&gt;anything&lt;/em&gt; about developing for Windows.&lt;/p&gt;
&lt;p&gt;That said, if I end up wanting to go lower it will be good to know how deep into the *nix  weeds I can go without dipping into the C like I did for &lt;a href=&#34;https://whynotestflight.com/excuses/can-i-open-a-serial-port-with-swift-part-ii/&#34;&gt;the serial port&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;So without further ado, here&amp;rsquo;s a catalog of the main players:&lt;/p&gt;
&lt;h3 id=&#34;filemanager&#34;&gt;FileManager&lt;/h3&gt;
&lt;p&gt;&lt;a href=&#34;https://developer.apple.com/documentation/foundation/filemanager&#34;&gt;https://developer.apple.com/documentation/foundation/filemanager&lt;/a&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&amp;ldquo;A convenient interface to the contents of the file system, and the primary means of interacting with it.&lt;/p&gt;&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;A file manager object lets you examine the contents of the file system and make changes to it. The FileManager class provides convenient access to a shared file manager object that is suitable for most types of file-related manipulations. A file manager object is typically your primary mode of interaction with the file system. You use it to locate, create, copy, and move files and directories. You also use it to get information about a file or directory or change some of its attributes.&amp;rdquo;&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;Largely used to get the URLs that will be used by other function, although URL seems to be moving into that space, too.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    FileManager.&lt;span style=&#34;color:#c6a0f6&#34;&gt;default&lt;/span&gt;.fileExists(atPath: url.path)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;url&lt;/span&gt; = URL.documentsDirectory.appending(path: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;fileName.txt&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;data-string-and-url&#34;&gt;Data, String and URL&lt;/h3&gt;
&lt;p&gt;These types have all been given read and sometimes write options. No separate &lt;a href=&#34;https://developer.apple.com/documentation/foundation/filemanager&#34;&gt;FileManager&lt;/a&gt; or &lt;a href=&#34;https://developer.apple.com/documentation/foundation/filehandle&#34;&gt;FileHandle&lt;/a&gt; required. For working with existing files.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://developer.apple.com/documentation/foundation/url&#34;&gt;https://developer.apple.com/documentation/foundation/url&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://developer.apple.com/documentation/foundation/url/3767315-lines&#34;&gt;https://developer.apple.com/documentation/foundation/url/3767315-lines&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://developer.apple.com/documentation/foundation/url/3767316-resourcebytes&#34;&gt;https://developer.apple.com/documentation/foundation/url/3767316-resourcebytes&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://developer.apple.com/documentation/foundation/url/asyncbytes&#34;&gt;https://developer.apple.com/documentation/foundation/url/asyncbytes&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://developer.apple.com/documentation/foundation/data&#34;&gt;https://developer.apple.com/documentation/foundation/data&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://developer.apple.com/documentation/foundation/data/1779858-write&#34;&gt;https://developer.apple.com/documentation/foundation/data/1779858-write&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://developer.apple.com/documentation/foundation/data/readingoptions&#34;&gt;https://developer.apple.com/documentation/foundation/data/readingoptions&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://developer.apple.com/documentation/foundation/data/writingoptions&#34;&gt;https://developer.apple.com/documentation/foundation/data/writingoptions&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://developer.apple.com/documentation/swift/string/init(contentsof:)&#34;&gt;https://developer.apple.com/documentation/swift/string/init(contentsof:)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://developer.apple.com/documentation/swift/string/write(to:)&#34;&gt;https://developer.apple.com/documentation/swift/string/write(to:)&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; someStringICareAbout.write(to: someURL, atomically: &lt;span style=&#34;color:#f5a97f&#34;&gt;true&lt;/span&gt;, encoding: .utf8)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;myString&lt;/span&gt; = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;(contentsOf: someURL, encoding: .utf8)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;myData&lt;/span&gt; = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; Data(contentsOf: someURL) 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; myData.write(to: someFileURL, options: [.atomic, .completeFileProtection])
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//NOTE: This function striped out empty lines the last I checked. &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;for&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; await line &lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt; url.lines {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    doSomething(with:line)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;stream&#34;&gt;*Stream&lt;/h3&gt;
&lt;p&gt;For when you don&amp;rsquo;t actually know to what or where the bytes will be going. File, socket, whatever.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;[Stream], &lt;a href=&#34;https://developer.apple.com/documentation/foundation/inputstream&#34;&gt;InputStream&lt;/a&gt; and &lt;a href=&#34;https://developer.apple.com/documentation/foundation/outputstream&#34;&gt;OutputStream&lt;/a&gt; as bridges to of &lt;a href=&#34;https://developer.apple.com/documentation/corefoundation/cfstream&#34;&gt;CFStream&lt;/a&gt;, &lt;a href=&#34;https://developer.apple.com/documentation/corefoundation/cfreadstream&#34;&gt;CFReadStream&lt;/a&gt; and &lt;a href=&#34;https://developer.apple.com/documentation/corefoundation/cfwritestream-rc8&#34;&gt;CFWriteStream&lt;/a&gt;?&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Honestly I haven&amp;rsquo;t used these much. I&amp;rsquo;m not clear on where they fit in the future of Swift and async file access. If I was going to these links would be a place to start.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;- Current GitHub: https://github.com/apple/swift-corelibs-foundation/blob/main/Sources/Foundation/Stream.swift
- 2020: https://forums.swift.org/t/is-it-possible-to-read-a-file-saved-in-sandbox-with-inputstream/37587
- https://forums.swift.org/t/make-inputstream-and-outputstream-methods-safe-and-swifty/23726/3
- https://forums.swift.org/t/inputstream-outputstream-differences-on-linux/34846/2
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;TextOutputStream, a protocol other processes, including &lt;code&gt;print&lt;/code&gt; can dump to, may play a role later down the line.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;- Github:https://github.com/apple/swift/blob/main/stdlib/public/core/OutputStream.swift
- Great howto article: https://nshipster.com/textoutputstream/
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I found other things called FileStreams floating around the Swift code, but it appears to be for specialized AV use?&lt;/p&gt;
&lt;h3 id=&#34;filehandle&#34;&gt;FileHandle&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;FileHandle&lt;/code&gt; doesn&amp;rsquo;t give raw C FileHandle access. Thanks to Wade&amp;rsquo;s &lt;a href=&#34;https://wadetregaskis.com/creating-temporary-files-safely-in-mac-apps/&#34;&gt;examinations&lt;/a&gt; we know it doesn&amp;rsquo;t let one create files, for example, (&amp;quot;_NSOpenFileDescriptor to do the actual file system calls. That calls open with only the flag O_WRONLY; it does not pass O_CREAT nor O_EXCL.&amp;quot;)&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://developer.apple.com/documentation/foundation/filehandle&#34;&gt;https://developer.apple.com/documentation/foundation/filehandle&lt;/a&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Although the read, accept, and wait operations themselves are performed asynchronously on background threads, the file handle uses a run loop source to monitor the operations and notify your code appropriately. Therefore, you must call those methods from your application’s main thread or from any thread where you’ve configured a run loop and are using it to process events.&lt;/p&gt;&lt;/blockquote&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;private&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;appendData&lt;/span&gt;(data:Data) &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;fileHandle&lt;/span&gt; = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; FileHandle(forWritingTo: storageUrl)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        fileHandle.seekToEndOfFile()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        fileHandle.write(data)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        fileHandle.closeFile()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//(from swift-argument-parser examples)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;mutating&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;lineCount&lt;/span&gt;() async &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;fileHandle&lt;/span&gt; = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; FileHandle(forReadingFrom: inputFile)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;lineCount&lt;/span&gt; = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; await fileHandle.bytes.lines.&lt;span style=&#34;color:#91d7e3&#34;&gt;reduce&lt;/span&gt;(into: &lt;span style=&#34;color:#f5a97f&#34;&gt;0&lt;/span&gt;) 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            { &lt;span style=&#34;color:#91d7e3&#34;&gt;count&lt;/span&gt;, &lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;count&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;+=&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;1&lt;/span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(lineCount)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;filewrapper&#34;&gt;FileWrapper&lt;/h3&gt;
&lt;p&gt;This is when a App&amp;rsquo;s Document has multiple items in a single &amp;ldquo;File&amp;rdquo;, which is perhaps better called a Document in this context. Not relevant&amp;hellip; yet?&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://developer.apple.com/documentation/foundation/filewrapper/&#34;&gt;https://developer.apple.com/documentation/foundation/filewrapper/&lt;/a&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&amp;ldquo;The FileWrapper class provides access to the attributes and contents of file system nodes. A file system node is a file, directory, or symbolic link. Instances of this class are known as file wrappers.&amp;rdquo;&lt;/p&gt;&lt;/blockquote&gt;
&lt;h3 id=&#34;nsfilepresenter-and-friends&#34;&gt;NSFilePresenter and friends&lt;/h3&gt;
&lt;p&gt;More Document sharing between Apps and people. Could be relevant, but is not cross platform?&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://developer.apple.com/documentation/foundation/nsfilepresenter&#34;&gt;https://developer.apple.com/documentation/foundation/nsfilepresenter&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;NSFilePresenter: The interface a file coordinator uses to inform an object presenting a file about changes to that file made elsewhere in the system&amp;hellip;.Objects that allow the user to view or edit the content of files or directories should adopt the NSFilePresenter protocol.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://developer.apple.com/documentation/foundation/nsfilecoordinator&#34;&gt;https://developer.apple.com/documentation/foundation/nsfilecoordinator&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;NSFileCoordinator: An object that coordinates the reading and writing of files and directories among file presenters.&lt;/p&gt;
&lt;h3 id=&#34;dispatchsource-and-friends&#34;&gt;DispatchSource and Friends&lt;/h3&gt;
&lt;p&gt;Apple platforms low-level system interaction handling.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://developer.apple.com/documentation/dispatch/dispatchsource&#34;&gt;https://developer.apple.com/documentation/dispatch/dispatchsource&lt;/a&gt;
&lt;a href=&#34;https://developer.apple.com/documentation/dispatch/dispatchsourcefilesystemobject&#34;&gt;https://developer.apple.com/documentation/dispatch/dispatchsourcefilesystemobject&lt;/a&gt;
&lt;a href=&#34;https://developer.apple.com/documentation/dispatch/dispatchsource/filesystemevent&#34;&gt;https://developer.apple.com/documentation/dispatch/dispatchsource/filesystemevent&lt;/a&gt;&lt;/p&gt;
&lt;h3 id=&#34;swift-system&#34;&gt;swift-system&lt;/h3&gt;
&lt;p&gt;Low-level system interactions for all the platforms Swift supports. Incredibly handy. Not nearly as easy as &amp;ldquo;Hey FileManager, fix it for me&amp;rdquo;, but good group of tools to look through before rolling ones own&amp;hellip;&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://github.com/apple/swift-system/&#34;&gt;https://github.com/apple/swift-system/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Backing library for Swift-NIO&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;System is a multi-platform library, not a cross-platform one. It provides a separate set of APIs and behaviors on every supported platform, closely reflecting the underlying OS interfaces. A single import will pull in the native platform interfaces specific for the targeted OS.&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;2024-04-03: &lt;a href=&#34;https://swiftpackageindex.com/apple/swift-nio/2.64.0/documentation/NIOFileSystem&#34;&gt;NIOFileSystem&lt;/a&gt; is the place to look, specifically. &lt;a href=&#34;https://forums.swift.org/t/what-is-the-best-way-to-work-with-the-file-system/71020/17&#34;&gt;Good forum discussion&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&#34;what-to-do&#34;&gt;What to do?&lt;/h2&gt;
&lt;p&gt;I am not convinced that I can do multi process managing of files without something more magic than the existing multi-platform options but won&amp;rsquo;t know without a little bit of try.&lt;/p&gt;
&lt;p&gt;Here&amp;rsquo;s the hello world. Available at &lt;a href=&#34;https://github.com/carlynorama/SimplePersist&#34;&gt;https://github.com/carlynorama/SimplePersist&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Tested on MacOS and Linux so far.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;Foundation&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;protocol&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;StringPersistable&lt;/span&gt;: LosslessStringConvertible, Sendable {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//the losses strings can&amp;#39;t have \n&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#ed8796&#34;&gt;init&lt;/span&gt;?(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; description: some StringProtocol)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;enum&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;PersistorError&lt;/span&gt;: Error {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#c6a0f6&#34;&gt;case&lt;/span&gt; unknownError(message: &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#c6a0f6&#34;&gt;case&lt;/span&gt; fileAttributeUnavailable(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; attributeName: &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#c6a0f6&#34;&gt;case&lt;/span&gt; stringNotDataEncodable
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;public&lt;/span&gt; actor BasicTextPersistor&amp;lt;Element: StringPersistable&amp;gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#ed8796&#34;&gt;private&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;fm&lt;/span&gt; = FileManager.&lt;span style=&#34;color:#c6a0f6&#34;&gt;default&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#ed8796&#34;&gt;private&lt;/span&gt;(&lt;span style=&#34;color:#c6a0f6&#34;&gt;set&lt;/span&gt;) &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;separator&lt;/span&gt;: &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#ed8796&#34;&gt;private&lt;/span&gt;(&lt;span style=&#34;color:#c6a0f6&#34;&gt;set&lt;/span&gt;) &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;encoding&lt;/span&gt;: &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;.Encoding = .utf8
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;storageUrl&lt;/span&gt;: URL
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#ed8796&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;fileExists&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; path: &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;) -&amp;gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;Bool&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    FileManager.&lt;span style=&#34;color:#c6a0f6&#34;&gt;default&lt;/span&gt;.fileExists(atPath: path)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#ed8796&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;fileExists&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; url: URL) -&amp;gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;Bool&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    FileManager.&lt;span style=&#34;color:#c6a0f6&#34;&gt;default&lt;/span&gt;.fileExists(atPath: url.path)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  @discardableResult
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#ed8796&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;touch&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; url: URL) -&amp;gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;Bool&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    FileManager.&lt;span style=&#34;color:#c6a0f6&#34;&gt;default&lt;/span&gt;.createFile(atPath: url.path, contents: &lt;span style=&#34;color:#f5a97f&#34;&gt;nil&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#ed8796&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;init&lt;/span&gt;(storageUrl: URL, separator: &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt; = &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\n&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;.storageUrl = storageUrl
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;.separator = separator
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;!&lt;/span&gt;&lt;span style=&#34;color:#f5a97f&#34;&gt;Self&lt;/span&gt;.fileExists(storageUrl) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f5a97f&#34;&gt;Self&lt;/span&gt;.touch(storageUrl)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#ed8796&#34;&gt;private&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;makeBlob&lt;/span&gt;(from array: [StringPersistable]) -&amp;gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    array.&lt;span style=&#34;color:#91d7e3&#34;&gt;map&lt;/span&gt; { &lt;span style=&#34;color:#f4dbd6&#34;&gt;$0&lt;/span&gt;.description }.joined(separator: separator)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#ed8796&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;write&lt;/span&gt;(contentsOf: [StringPersistable]) async &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; makeBlob(from: contentsOf).write(to: storageUrl, atomically: &lt;span style=&#34;color:#f5a97f&#34;&gt;true&lt;/span&gt;, encoding: .utf8)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//Do you need appends to be atomic? That is, as supported by the O_APPEND flag for open.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#ed8796&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;append&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; item: Element) async &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;data&lt;/span&gt; = &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;separator&lt;span style=&#34;color:#a6da95&#34;&gt;)\(&lt;/span&gt;item.description&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;.data(using: encoding) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; appendData(data: data)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    } &lt;span style=&#34;color:#c6a0f6&#34;&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#c6a0f6&#34;&gt;throw&lt;/span&gt; PersistorError.stringNotDataEncodable
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#ed8796&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;append&lt;/span&gt;(contentsOf: [Element]) async &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;data&lt;/span&gt; = &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;separator&lt;span style=&#34;color:#a6da95&#34;&gt;)\(&lt;/span&gt;makeBlob&lt;span style=&#34;color:#a6da95&#34;&gt;(&lt;/span&gt;from: contentsOf&lt;span style=&#34;color:#a6da95&#34;&gt;))&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;.data(using: encoding) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; appendData(data: data)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    } &lt;span style=&#34;color:#c6a0f6&#34;&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#c6a0f6&#34;&gt;throw&lt;/span&gt; PersistorError.stringNotDataEncodable
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#ed8796&#34;&gt;private&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;appendData&lt;/span&gt;(data: Data) &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;fileHandle&lt;/span&gt; = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; FileHandle(forWritingTo: storageUrl)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    fileHandle.seekToEndOfFile()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    fileHandle.write(data)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    fileHandle.closeFile()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//this is async for the actor, not the file i/o&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  @available(macOS &lt;span style=&#34;color:#f5a97f&#34;&gt;13.0&lt;/span&gt;, iOS &lt;span style=&#34;color:#f5a97f&#34;&gt;16.0&lt;/span&gt;, &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;*&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#ed8796&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;retrieve&lt;/span&gt;() async &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; -&amp;gt; [Element] {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;string&lt;/span&gt; = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;(contentsOf: storageUrl)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; string.&lt;span style=&#34;color:#91d7e3&#34;&gt;split&lt;/span&gt;(separator: separator).compactMap({
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      Element.&lt;span style=&#34;color:#ed8796&#34;&gt;init&lt;/span&gt;(&lt;span style=&#34;color:#f4dbd6&#34;&gt;$0&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    })
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  @available(macOS &lt;span style=&#34;color:#f5a97f&#34;&gt;13.0&lt;/span&gt;, iOS &lt;span style=&#34;color:#f5a97f&#34;&gt;16.0&lt;/span&gt;, &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;*&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#ed8796&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;retrieveAvailable&lt;/span&gt;() async -&amp;gt; [Element] {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;do&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; await retrieve()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    } &lt;span style=&#34;color:#c6a0f6&#34;&gt;catch&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; []
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#ed8796&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;lastModified&lt;/span&gt;() &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; -&amp;gt; Date {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//works in linux?&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//if let date = try storageUrl.resourceValues(forKeys: [.contentModificationDateKey]).contentModificationDate&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;attribute&lt;/span&gt; = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; fm.attributesOfItem(atPath: storageUrl.path)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;date&lt;/span&gt; = attribute[FileAttributeKey.modificationDate] &lt;span style=&#34;color:#c6a0f6&#34;&gt;as&lt;/span&gt;? Date {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; date
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    } &lt;span style=&#34;color:#c6a0f6&#34;&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#c6a0f6&#34;&gt;throw&lt;/span&gt; PersistorError.fileAttributeUnavailable(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;modificationDate&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//The corresponding value is an NSNumber object containing an unsigned long long.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//Important&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//If the file has a resource fork, the returned value does not include the size of the resource fork.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#ed8796&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;size&lt;/span&gt;() &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; -&amp;gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;Int&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;attribute&lt;/span&gt; = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; FileManager.&lt;span style=&#34;color:#c6a0f6&#34;&gt;default&lt;/span&gt;.attributesOfItem(atPath: storageUrl.path)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;size&lt;/span&gt; = attribute[FileAttributeKey.size] &lt;span style=&#34;color:#c6a0f6&#34;&gt;as&lt;/span&gt;? &lt;span style=&#34;color:#91d7e3&#34;&gt;Int&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; size
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    } &lt;span style=&#34;color:#c6a0f6&#34;&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#c6a0f6&#34;&gt;throw&lt;/span&gt; PersistorError.fileAttributeUnavailable(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;size&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#if&lt;/span&gt; &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;os&lt;/span&gt;(&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;Linux&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#ed8796&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;Foundation&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//https://github.com/apple/swift-corelibs-foundation/blob/36a411b304063de2cbd3fe06adc662e7648d5a9d/Sources/Foundation/URL.swift#L749&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;TODO:&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt; isDirectory one, too.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#ed8796&#34;&gt;extension&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;URL&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;appending&lt;/span&gt;(path: &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;) -&amp;gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;Self&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;.appendingPathComponent(path)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#endif&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;things-to-think-about-when-saving-data&#34;&gt;Things to think about when saving Data&lt;/h2&gt;
&lt;p&gt;The journalism classic article checklist &amp;ldquo;Who, what, when, where, why?&amp;rdquo; provides just as much utility when trying to decide how and if to save certain data.&lt;/p&gt;
&lt;p&gt;This is just a quick mental dump of what&amp;rsquo;s in the back of my mind when picking a mechanism to store data.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;input disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; Quantity and shape of the data?
&lt;ul&gt;
&lt;li&gt;&lt;input disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; how much?&lt;/li&gt;
&lt;li&gt;&lt;input disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; how often does it change?
&lt;ul&gt;
&lt;li&gt;&lt;input disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; modified&lt;/li&gt;
&lt;li&gt;&lt;input disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; appended&lt;/li&gt;
&lt;li&gt;&lt;input disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; removed&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;input disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; does it arrive in the shape it will be stored?&lt;/li&gt;
&lt;li&gt;&lt;input disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; will subsections need to be selectively accessed?&lt;/li&gt;
&lt;li&gt;&lt;input disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; how many sources does it come from?
&lt;ul&gt;
&lt;li&gt;[] number of process types&lt;/li&gt;
&lt;li&gt;[] number of processes at a time&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;input disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; what&amp;rsquo;s the time frame for its value (nanoseconds vs archive quality)?&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;input disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; Data usage
&lt;ul&gt;
&lt;li&gt;&lt;input disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; does it leave in the shape it&amp;rsquo;s stored?&lt;/li&gt;
&lt;li&gt;&lt;input disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; how many processes need the information to do their work?
&lt;ul&gt;
&lt;li&gt;&lt;input disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; number of process types&lt;/li&gt;
&lt;li&gt;&lt;input disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; number of processes at a time&lt;/li&gt;
&lt;li&gt;&lt;input disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; honestly, how &amp;ldquo;fresh&amp;rdquo; does the data need to be for the work to be correct.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;input disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; Semantic value
&lt;ul&gt;
&lt;li&gt;&lt;input disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; is it identifying?&lt;/li&gt;
&lt;li&gt;&lt;input disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; is it private?&lt;/li&gt;
&lt;li&gt;&lt;input disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; is it legally protected?&lt;/li&gt;
&lt;li&gt;&lt;input disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; is it hard to reproduce?&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;input disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; Machine Trust
&lt;ul&gt;
&lt;li&gt;&lt;input disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; are all the processes that need it inside a verifiable trust?&lt;/li&gt;
&lt;li&gt;&lt;input disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; who &lt;em&gt;needs&lt;/em&gt; to write? (can it be mediated?)&lt;/li&gt;
&lt;li&gt;&lt;input disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; who &lt;em&gt;needs&lt;/em&gt; to read? (can it be mediated?)&lt;/li&gt;
&lt;li&gt;&lt;input disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; do all the machines read and write data the same way?&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;input disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; Low-level Human Operator Trust
&lt;ul&gt;
&lt;li&gt;&lt;input disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; expertise with the data&lt;/li&gt;
&lt;li&gt;&lt;input disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; expertise with computers&lt;/li&gt;
&lt;li&gt;&lt;input disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; current methods&lt;/li&gt;
&lt;li&gt;&lt;input disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; conditions of labor
&lt;ul&gt;
&lt;li&gt;will they be overworked and tired?&lt;/li&gt;
&lt;li&gt;will they be bribeable?&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
</description>
    </item>
    
    
    
    <item>
      <title>That new-Ubuntu smell</title>
      <link>https://whynotestflight.com/excuses/that-new-ubuntu-smell/</link>
      <pubDate>Thu, 15 Feb 2024 00:00:00 +0000</pubDate>
      
      <guid>https://whynotestflight.com/excuses/that-new-ubuntu-smell/</guid>
      <description>&lt;p&gt;Installing Linux has gotten pretty easy.&lt;/p&gt;
&lt;p&gt;Depending on the flavor needed and the destination two utilities come in handy to make the needed USB boot sticks:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://www.raspberrypi.com/software/&#34;&gt;RaspberryPi Imager&lt;/a&gt; for RaspberryPi destinations&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://etcher.balena.io/&#34;&gt;balena etcher&lt;/a&gt; for everything else.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I&amp;rsquo;m using Ubuntu 22: &lt;a href=&#34;https://ubuntu.com/download/desktop&#34;&gt;https://ubuntu.com/download/desktop&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;To do this install I put the imaged USB drive into the target machine and held down the DEL key. F7 would have worked, but DEL goes to the boot settings and I can set the machine to always prefer the key if it&amp;rsquo;s plugged in. Since this machine will likely get re-imaged fairly often, that&amp;rsquo;s what I want.&lt;/p&gt;
&lt;p&gt;Here&amp;rsquo;s some common commands used during a setup.&lt;/p&gt;
&lt;p&gt;Why not Docker? I&amp;rsquo;ll use Docker fine for DigitalOcean droplets or GitHub Actions or whatever. I installed something that uses it (swiftly). I don&amp;rsquo;t need it for what I&amp;rsquo;m doing in general though. I have a bash script for when I&amp;rsquo;m not rethinking the set up. Writing things down took longer than doing it.&lt;/p&gt;
&lt;h2 id=&#34;hardware-fixes&#34;&gt;Hardware Fixes&lt;/h2&gt;
&lt;p&gt;My new little box &lt;a href=&#34;https://www.cnx-software.com/2023/07/07/fixing-wifi-6-on-linux-in-alder-lake-n-mini-pcs-intel-n95-n100-core-i3-n300/&#34;&gt;couldn&amp;rsquo;t see its wifi card&lt;/a&gt;. Fix worked.  Required ethernet.&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;  ###  resolving wifi issues
    3  cat /etc/motd
    4  cat /etc/issue
    8  sudo dmesg | grep wifi
    9  sudo add-apt-repository ppa:cappelikan/ppa
   10  sudo apt update &amp;amp;&amp;amp; sudo apt full-upgrade
   41  lshw
  139  ip
  140  ip link show
  141  ip address show
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&#34;git&#34;&gt;Git&lt;/h2&gt;
&lt;p&gt;&lt;a href=&#34;https://git-scm.com/book/en/v2/Getting-Started-First-Time-Git-Setup&#34;&gt;https://git-scm.com/book/en/v2/Getting-Started-First-Time-Git-Setup&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;On a properly configured machine run &lt;code&gt;cat ~/.gitconfig&lt;/code&gt; to see what&amp;rsquo;s there. If it&amp;rsquo;s exactly right and it&amp;rsquo;s easy, copy it over. Otherwise here are the basics.&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;  247  git config --global init.defaultBranch main
  248  git config --global user.name &amp;#34;$(YOUR_NAME)&amp;#34;
  249  git config --global user.email $(YOUR_EMAIL)
  250  git config --global alias.start-repo &amp;#39;!git init . &amp;amp;&amp;amp; git add . &amp;amp;&amp;amp; git commit --allow-empty -m &amp;#34;Initialize repository&amp;#34;&amp;#39;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;On Linux the global .gitignore with .DS_Store in it is less of a big deal to do.&lt;/p&gt;
&lt;p&gt;The default editor can be changed in two ways, for git only of for the system:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;## for the system
update-alternatives --display editor  # on Ubuntu will likely be nano
sudo update-alternatives --config editor #dialog with currently installed editors

## just for git
git config --global core.editor $(YOUR_FAV_EDITOR_AND_ITS_WAIT_FLAG)
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;When updating the editor for git, if your editor has a &lt;a href=&#34;https://stackoverflow.com/questions/68975299/why-should-i-use-wait-when-selecting-my-default-editor-in-git&#34;&gt;wait flag&lt;/a&gt;, &lt;a href=&#34;https://www.atlassian.com/git/tutorials/setting-up-a-repository/git-config&#34;&gt;use it&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Also, depending on what I&amp;rsquo;ll be doing on the image, the git extension for large file storage can also be handy.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://git-lfs.com/&#34;&gt;https://git-lfs.com/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/git-lfs/git-lfs/blob/main/INSTALLING.md&#34;&gt;https://github.com/git-lfs/git-lfs/blob/main/INSTALLING.md&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;  269  sudo apt-get install git-lfs
  270  git lfs install
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&#34;vscode&#34;&gt;VSCode&lt;/h2&gt;
&lt;p&gt;&lt;a href=&#34;https://code.visualstudio.com/docs/setup/linux&#34;&gt;https://code.visualstudio.com/docs/setup/linux&lt;/a&gt;&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;  ###  installing VSCode
   23  cd Downloads/  # got it from the page auto download. 
   24  sudo apt install ./code_1.86.2-1707854558_amd64.deb 
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Like with git can check a known good machine get what extensions to install if not already using &lt;a href=&#34;https://code.visualstudio.com/docs/editor/settings-sync&#34;&gt;Settings Sync&lt;/a&gt; or a &lt;a href=&#34;https://code.visualstudio.com/docs/editor/profiles&#34;&gt;Profile&lt;/a&gt;.&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;## old machine
code --list-extensions &amp;gt; vscode-extensions.list 
## new machine
cat vscode-extensions.list | xargs -L 1 code --install-extension 
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&#34;swift&#34;&gt;Swift&lt;/h2&gt;
&lt;p&gt;&lt;a href=&#34;https://whynotestflight.com/excuses/now-i-need-linux-to-test-on./&#34;&gt;Last time&lt;/a&gt; I used the &lt;a href=&#34;https://www.swift.org/install/linux/#installation-via-tarball&#34;&gt;tarball&lt;/a&gt;. This time I&amp;rsquo;m using &lt;a href=&#34;https://github.com/swift-server/swiftly&#34;&gt;swiftly&lt;/a&gt; as an experiment. (&lt;a href=&#34;https://github.com/stevapple/swiftbox&#34;&gt;swiftbox&lt;/a&gt; and &lt;a href=&#34;https://github.com/kylef/swiftenv&#34;&gt;swiftenv&lt;/a&gt; also great choices.) Swiftly actually uses the &lt;a href=&#34;https://github.com/apple/swift-docker&#34;&gt;official docker images&lt;/a&gt; to do its thing.&lt;/p&gt;
&lt;p&gt;The actual install for swiftly: very smooth. 5 out of 5 stars using it to get to the nightly build up and running. Most of these commands were exploring if I could help the repl find lldb without the known needed extra install and fix. I could not. Moved on.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/llvm/llvm-project/issues/55575&#34;&gt;https://github.com/llvm/llvm-project/issues/55575&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://forums.swift.org/t/swift-repl-no-module-named-lldb/60275/18&#34;&gt;https://forums.swift.org/t/swift-repl-no-module-named-lldb/60275/18&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;  ###  installing swift / swiftly
   12  sudo apt install curl
   13  curl -L https://swift-server.github.io/swiftly/swiftly-install.sh | bash
   14  . $HOME/.local/share/swiftly/env.sh
   15  swiftly install latest
   16  which which clang make git swift lldb

   29  ls ../.local/bin/clang
   30  ls -la ../.local/bin/
   40  ldd `which swift`
   60  echo $PATH
   63  cat ~/.bashrc
   64  hash -r
   65  swift repl
   66  swiftly use latest
   77  code ~/.bashrc
   78  which python3
   79  ls /usr/lib/llvm-14 #nope, not there yet
   82  ls -la /usr/lib
   84  ls -alrth
  127  lldb --help
  128  lldb --python-path  ##&amp;lt;--- AND HERE IS THE SAME ERROR as REPL
  
  146  swift package init --type tool
  147  swift run  #works
 
  ### spm also worked fine for 
  165  swiftly install main-snapshot
  165  swiftly use main-snapshot
  168  swiftly install 5.10-snapshot
  170  swiftly use 5.10-snapshot
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&#34;homebrew&#34;&gt;Homebrew&lt;/h2&gt;
&lt;p&gt;I primarily use apt-get, but I recently learned homebrew was a thing on Linux, so why not?&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://github.com/Homebrew/brew#donations&#34;&gt;https://github.com/Homebrew/brew#donations&lt;/a&gt;&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;###  installing homebrew
216  sudo apt-get install propcps

218  sudo apt-get install build-essential # &amp;lt;== important would do anyway

219  /bin/bash -c &amp;#34;$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)&amp;#34;
220  (echo; echo &amp;#39;eval &amp;#34;$(/home/linuxbrew/.linuxbrew/bin/brew shellenv)&amp;#34;&amp;#39;) &amp;gt;&amp;gt; /home/$(YOUR_USER)/.bashrc
221  eval &amp;#34;$(/home/linuxbrew/.linuxbrew/bin/brew shellenv)&amp;#34;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Makes its own user. Fascinating.&lt;/p&gt;
&lt;h2 id=&#34;some-of-the-other-faves&#34;&gt;Some of the other faves&lt;/h2&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;  278 sudo apt-get install ffmpeg imagemagick libpng-dev cmake hugo
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&#34;not-yet&#34;&gt;Not Yet&lt;/h2&gt;
&lt;p&gt;All of these will be done but on demand. pyenv I&amp;rsquo;ve used via homebrew on macOS. Not sure if I&amp;rsquo;ll do it that way on Ubuntu.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;pyenv (python env manager)&lt;/li&gt;
&lt;li&gt;nvm (node env manager)&lt;/li&gt;
&lt;li&gt;OpenUSD (Big. Specific python needs.)&lt;/li&gt;
&lt;/ul&gt;
</description>
    </item>
    
    
    
    <item>
      <title>(wait, how&#39;d I get the blog to do that?)</title>
      <link>https://whynotestflight.com/excuses/wait-howd-i-get-the-blog-to-do-that/</link>
      <pubDate>Mon, 12 Feb 2024 00:00:00 +0000</pubDate>
      
      <guid>https://whynotestflight.com/excuses/wait-howd-i-get-the-blog-to-do-that/</guid>
      <description>&lt;p&gt;I specifically use a static blogging software written in a language I don&amp;rsquo;t know so I won&amp;rsquo;t be too tempted to spend all my time screwing with it instead of just getting things down. The typography needs some serious work.  I have tweaked some things, though.  So before I forget what everything in the hugo.toml does&amp;hellip;&lt;/p&gt;
&lt;h2 id=&#34;including-html&#34;&gt;Including HTML&lt;/h2&gt;
&lt;p&gt;This was for embedding p5.js scripts and X3D files. I use the default markup renderer.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://gohugo.io/getting-started/configuration-markup/&#34;&gt;https://gohugo.io/getting-started/configuration-markup/&lt;/a&gt;&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-toml&#34; data-lang=&#34;toml&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;[markup.goldmark.renderer]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# Allows HTML in Markdown&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  unsafe = &lt;span style=&#34;color:#f5a97f&#34;&gt;true&lt;/span&gt; &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# default is false&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;remapping-posts-to-excuses-on-the-qt&#34;&gt;remapping &amp;ldquo;posts&amp;rdquo; to &amp;ldquo;excuses&amp;rdquo; on the QT&lt;/h2&gt;
&lt;p&gt;&lt;a href=&#34;https://whynotestflight.com/excuses/getting-scripty/&#34;&gt;From about a year ago.&lt;/a&gt; (end of page.)&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://github.com/wowchemy/wowchemy-hugo-themes/issues/356&#34;&gt;https://github.com/wowchemy/wowchemy-hugo-themes/issues/356&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;(note that pageRef gets used for internal pages now. url is only for external pages.)&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-toml&#34; data-lang=&#34;toml&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;[permalinks]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  posts = &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;excuses/:title&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;[menu]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  [[menu.main]]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    identifier = &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;posts&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    name = &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;posts&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    title = &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;posts&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    pageRef = &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;/excuses/&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    weight = &lt;span style=&#34;color:#f5a97f&#34;&gt;10&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;code-block-formatting&#34;&gt;Code block formatting&lt;/h2&gt;
&lt;p&gt;&lt;a href=&#34;https://whynotestflight.com/excuses/hunh...-my-code-lines-are-really-long/&#34;&gt;From July 2023&lt;/a&gt;&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;theme = &amp;#34;etch&amp;#34;
enableInlineShortcodes = true
[markup]
  [markup.highlight]
    lineNos = false
    codeFences = true
    noClasses = false
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&#34;having-a-storage-folder-to-put-scrap-files-in&#34;&gt;Having a &amp;ldquo;storage&amp;rdquo; folder to put scrap files in&lt;/h2&gt;
&lt;p&gt;Didn&amp;rsquo;t document at the time but here ae some references:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://gohugo.io/hugo-modules/configuration/#module-config-mounts&#34;&gt;https://gohugo.io/hugo-modules/configuration/#module-config-mounts&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://gohugo.io/hugo-modules/use-modules/&#34;&gt;https://gohugo.io/hugo-modules/use-modules/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-toml&#34; data-lang=&#34;toml&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;[module]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;[[module.mounts]]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  excludeFiles = &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#39;/posts/**/storage&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  source = &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#39;content&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  target = &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#39;content&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;using-anchor-tags&#34;&gt;Using anchor tags&lt;/h2&gt;
&lt;p&gt;I forget. every. time.&lt;/p&gt;
&lt;!--Note: putting bad short codes in a post screws with hugo. even inside code fences.

- https://discourse.gohugo.io/t/how-is-the-hugo-doc-site-showing-shortcodes-in-code-blocks/9074/13

I used above as a work around. 

`[link text B]({&amp;lbrace;&lt; relref  &#34;other-page-folder#header-id-text&#34; &gt;}&amp;rbrace;)` --&gt;
&lt;ul&gt;
&lt;li&gt;[link text A]({{&amp;lt; relref  other-page-folder &amp;gt;}})&lt;/li&gt;
&lt;li&gt;[link text B]({{&amp;lt; relref  &amp;ldquo;other-page-folder#header-id-text&amp;rdquo; &amp;gt;}})&lt;/li&gt;
&lt;li&gt;[link text C]({{&amp;lt; &amp;ldquo;#header-id-text&amp;rdquo; &amp;gt;}})&lt;/li&gt;
&lt;li&gt;adding a custom anchor? &lt;code&gt;{#usdcat}&lt;/code&gt; at the end of a heading worked.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Adding the below to the toml means custom block attributes are also now possible.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-toml&#34; data-lang=&#34;toml&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;[markup.goldmark.parser.attribute]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# Allows custom attributes &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  block = &lt;span style=&#34;color:#f5a97f&#34;&gt;true&lt;/span&gt; &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# default is false&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-hugo&#34; data-lang=&#34;hugo&#34;&gt;my fancy paragraph that I will want to link to again
{id=&amp;#34;id-anchor-name-wanted-for-block&amp;#34;}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The above will slip that id attribute into the &lt;code&gt;&amp;lt;p&amp;gt;&lt;/code&gt; or other block tag, which then can be used as an anchor.&lt;/p&gt;
&lt;h2 id=&#34;adding-a-series&#34;&gt;Adding a Series&lt;/h2&gt;
&lt;p&gt;I don&amp;rsquo;t love the way the layout currently happens, but it took 3 pretty simple steps:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;create the taxonomy
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://gohugo.io/content-management/taxonomies/&#34;&gt;https://gohugo.io/content-management/taxonomies/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;create the partial / other templates
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://gohugo.io/templates/taxonomy-templates/&#34;&gt;https://gohugo.io/templates/taxonomy-templates/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;add the partial to the default layout (this overrides the theme&amp;rsquo;s)
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://gohugobrasil.netlify.app/themes/customizing/&#34;&gt;https://gohugobrasil.netlify.app/themes/customizing/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;hugotoml&#34;&gt;hugo.toml&lt;/h3&gt;
&lt;p&gt;Once a custom taxonomy gets added the &lt;a href=&#34;https://gohugo.io/content-management/taxonomies/#default-taxonomies&#34;&gt;default ones&lt;/a&gt; go away so &lt;code&gt;tags&lt;/code&gt; has to be there, too.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-toml&#34; data-lang=&#34;toml&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;[taxonomies]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   series = &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;series&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   tag = &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;tags&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;layouts--partials--serieshtml&#34;&gt;layouts &amp;gt; partials &amp;gt; series.html&lt;/h3&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-hugo&#34; data-lang=&#34;hugo&#34;&gt;{{ if .Params.series }}
&amp;lt;div&amp;gt;
    &amp;lt;h4&amp;gt;This article is part of a series.&amp;lt;/h4&amp;gt;
    &amp;lt;ul class=&amp;#34;list-group&amp;#34;&amp;gt;
        {{ range $num,$post := (index .Site.Taxonomies.series (index .Params.series 0 | urlize)).Pages.ByDate }}
            {{ if eq $post.Permalink $.Page.Permalink }}
                &amp;lt;li class=&amp;#34;list-group-item active&amp;#34;&amp;gt;
                    Part {{ add $num 1 }}: This Article
                &amp;lt;/li&amp;gt;
            {{ else }}
                &amp;lt;li class=&amp;#34;list-group-item&amp;#34;&amp;gt;
                    &amp;lt;a href=&amp;#34;{{$post.Permalink}}&amp;#34;&amp;gt;
                        Part {{ add $num 1 }}: {{ $post.Params.title}}
                    &amp;lt;/a&amp;gt;
                &amp;lt;/li&amp;gt;
            {{end}}
        {{end}}
    &amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
{{end}}
&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=&#34;layouts--_default--singlehtml&#34;&gt;layouts &amp;gt; _default &amp;gt; single.html&lt;/h3&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-hugo&#34; data-lang=&#34;hugo&#34;&gt;{{ define &amp;#34;main&amp;#34; }}
&amp;lt;article&amp;gt;
    &amp;lt;header id=&amp;#34;post-header&amp;#34;&amp;gt;
        &amp;lt;h1&amp;gt;{{ .Title }}&amp;lt;/h1&amp;gt;
        &amp;lt;div&amp;gt;
        {{- if isset .Params &amp;#34;date&amp;#34; -}}
            {{ if eq .Lastmod .Date }}
                &amp;lt;time&amp;gt;{{ .Date | time.Format (i18n &amp;#34;post.created&amp;#34;) }}&amp;lt;/time&amp;gt;
            {{ else }}
                &amp;lt;time&amp;gt;{{ .Lastmod | time.Format (i18n &amp;#34;post.updated&amp;#34;) }}&amp;lt;/time&amp;gt;
            {{ end }}
        {{- end -}}
        &amp;lt;/div&amp;gt;
    &amp;lt;/header&amp;gt;
    {{ partial &amp;#34;series.html&amp;#34; . }}
    {{- .Content -}}
    {{ partial &amp;#34;series.html&amp;#34; . }}
&amp;lt;/article&amp;gt;
{{ end }}
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&#34;adding-a-tags-page&#34;&gt;Adding a tags page&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://gohugo.io/templates/taxonomy-templates/#order-alphabetically-example&#34;&gt;https://gohugo.io/templates/taxonomy-templates/#order-alphabetically-example&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://discourse.gohugo.io/t/tag-cloud/6335&#34;&gt;https://discourse.gohugo.io/t/tag-cloud/6335&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://discourse.gohugo.io/t/taxonomy-list-template-pages-vs-data-terms/45919&#34;&gt;https://discourse.gohugo.io/t/taxonomy-list-template-pages-vs-data-terms/45919&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://gohugo.io/templates/data-templates/&#34;&gt;https://gohugo.io/templates/data-templates/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://gohugo.io/templates/taxonomy-templates/&#34;&gt;https://gohugo.io/templates/taxonomy-templates/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In addition to having it listed in the taxonomies section of the toml&amp;hellip;&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-toml&#34; data-lang=&#34;toml&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  [[menu.main]]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    name = &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;tags&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    identifier = &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;tags&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    title = &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;tags&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    pageRef = &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;/tags&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    weight = &lt;span style=&#34;color:#f5a97f&#34;&gt;20&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;layoutstagslisthtml&#34;&gt;layouts/tags/list.html&lt;/h3&gt;
&lt;p&gt;combination of a &lt;a href=&#34;https://discourse.gohugo.io/t/tag-cloud/6335&#34;&gt;tag cloud example&lt;/a&gt; and an example on how to &lt;a href=&#34;https://gohugo.io/templates/taxonomy-templates/#order-alphabetically-example&#34;&gt;list things alphabetically&lt;/a&gt; from the hugo website.&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-hugo&#34; data-lang=&#34;hugo&#34;&gt;{{ define &amp;#34;main&amp;#34; }}
&amp;lt;h3&amp;gt;{{ .Title }}&amp;lt;/h3&amp;gt;
&amp;lt;div id=&amp;#34;theme-tagcloud&amp;#34; class=&amp;#34;col-sm-12&amp;#34; style=&amp;#34;margin-top: 15px;&amp;#34;&amp;gt;
    {{ range .Data.Terms.ByCount }}
    &amp;lt;a href=&amp;#34;{{ .Page.Permalink }}&amp;#34; class=&amp;#34;btn btn-default&amp;#34; role=&amp;#34;button&amp;#34; style=&amp;#34;padding-right: 5px; padding-left: 5px;&amp;#34; &amp;gt;{{ .Page.Title }} &amp;lt;!--&amp;lt;span class=&amp;#34;badge&amp;#34;&amp;gt;({{ .Count }})&amp;lt;/span&amp;gt;--&amp;gt;&amp;lt;/a&amp;gt;
  {{ end }}
&amp;lt;/div&amp;gt;
{{ end }}
&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=&#34;layoutstagstermhtml&#34;&gt;layouts/tags/term.html&lt;/h3&gt;
&lt;p&gt;copy of the taxonomy.html from the &lt;a href=&#34;https://themes.gohugo.io/themes/etch/&#34;&gt;etch theme&lt;/a&gt;.&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-hugo&#34; data-lang=&#34;hugo&#34;&gt;{{ define &amp;#34;main&amp;#34; }}
&amp;lt;h3&amp;gt;{{ .Title }}&amp;lt;/h3&amp;gt;
&amp;lt;ul id=&amp;#34;posts&amp;#34;&amp;gt;
{{- range .Pages }}
    {{ .Render &amp;#34;li&amp;#34; }}
{{- end }}
&amp;lt;/ul&amp;gt;
{{ end }}
&lt;/code&gt;&lt;/pre&gt;</description>
    </item>
    
    
    
    <item>
      <title>Okay, but how about all the way up to the View?</title>
      <link>https://whynotestflight.com/excuses/okay-but-how-about-all-the-way-up-to-the-view/</link>
      <pubDate>Mon, 12 Feb 2024 00:00:00 +0000</pubDate>
      
      <guid>https://whynotestflight.com/excuses/okay-but-how-about-all-the-way-up-to-the-view/</guid>
      <description>&lt;h2 id=&#34;related-repo&#34;&gt;Related Repo&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Lines &lt;a href=&#34;https://github.com/carlynorama/lines&#34;&gt;https://github.com/carlynorama/lines&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;relevant tag: F_helloAppGroup&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;intro&#34;&gt;Intro&lt;/h2&gt;
&lt;p&gt;Sharing information between processes has been &lt;a href=&#34;https://en.wikipedia.org/wiki/Inter-process_communication&#34;&gt;solved many ways&lt;/a&gt;. It&amp;rsquo;s already being solved in part of the app by an &lt;a href=&#34;https://developer.apple.com/documentation/bundleresources/information_property_list/nsextension&#34;&gt;NSExtension&lt;/a&gt; which probably gets backed by &lt;a href=&#34;https://developer.apple.com/documentation/xpc&#34;&gt;XPC&lt;/a&gt; and gives us &lt;a href=&#34;https://developer.apple.com/documentation/safariservices/&#34;&gt;SafariServices&lt;/a&gt;.  To do the same we&amp;rsquo;d need to have Lines have its own hooks into the &lt;a href=&#34;https://developer.apple.com/documentation/xpc/launchd&#34;&gt;launchd&lt;/a&gt; &lt;a href=&#34;https://en.wikipedia.org/wiki/Launchd&#34;&gt;system&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;An easier path, one of the common ways Apple developers get told to solve the communication problem between their current app and their future restarted app is &lt;a href=&#34;https://developer.apple.com/documentation/foundation/userdefaults/&#34;&gt;UserDefaults&lt;/a&gt;. With an &lt;code&gt;App Group&lt;/code&gt; those UserDefaults can be shared across multiple processes on the same device, e.g. different apps, their Widgets, a web extension, etc.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ve used app groups once before in an iPad based project, so some things I knew and somethings I did not. I&amp;rsquo;d already learned about &lt;a href=&#34;https://developer.apple.com/help/account/manage-identifiers/register-an-app-group&#34;&gt;registering&lt;/a&gt; an iOS app group. I did not realize the &lt;a href=&#34;https://developer.apple.com/documentation/xcode/configuring-app-groups&#34;&gt;configuration&lt;/a&gt; was so different between macOS and iOS. I hadn&amp;rsquo;t made a project that need multiple entitlement files before either.  So I wasted some time.&lt;/p&gt;
&lt;p&gt;At the end of this post the project will have a very simplistic 2 channel communication protocol set up between the Lines target and the LineGrabber target, both on iOS and macOS, reusing the same code. UserDefaults are not wires. It&amp;rsquo;s not expensive to make specific channels for specific purposes. There&amp;rsquo;s no BOM increase for another SPI bus, etc. But we&amp;rsquo;re not doing anything too fancy yet so I went with the inbox for A is the outbox for B model &lt;a href=&#34;https://learn.sparkfun.com/tutorials/terminal-basics/all&#34;&gt;RXTX style&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Lines&lt;/code&gt; will update it&amp;rsquo;s GUI based on what it finds in the UserDefaults.&lt;/p&gt;
&lt;h2 id=&#34;references&#34;&gt;References&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://developer.apple.com/documentation/xcode/configuring-app-groups&#34;&gt;https://developer.apple.com/documentation/xcode/configuring-app-groups&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://developer.apple.com/help/account/manage-identifiers/register-an-app-group&#34;&gt;https://developer.apple.com/help/account/manage-identifiers/register-an-app-group&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://developer.apple.com/documentation/bundleresources/entitlements/com_apple_security_application-groups&#34;&gt;https://developer.apple.com/documentation/bundleresources/entitlements/com_apple_security_application-groups&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://developer.apple.com/documentation/foundation/userdefaults/&#34;&gt;https://developer.apple.com/documentation/foundation/userdefaults/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://jeffreyfulton.ca/blog/2018/02/userdefaults-limitations-and-alternatives&#34;&gt;https://jeffreyfulton.ca/blog/2018/02/userdefaults-limitations-and-alternatives&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;setting-up-the-appgroups&#34;&gt;Setting up the AppGroups&lt;/h2&gt;
&lt;p&gt;In provisionedOS land (iOS &amp;amp; the Tablettes) where Apple has made the call that consumer data safety out ranks everything else, one has to notify Apple that there will be an App Group by &lt;a href=&#34;https://developer.apple.com/help/account/manage-identifiers/register-an-app-group&#34;&gt;linking it to a developer account&lt;/a&gt;. This prevents non authorized apps from just wandering up to the app group and asking for what&amp;rsquo;s in there.&lt;/p&gt;
&lt;p&gt;On macOS CMD+SHFT+G in the Finder, point it towards &lt;code&gt;/Users/$YOUR_USERNAME/Library/Group Containers/&lt;/code&gt; and take a poke around. It&amp;rsquo;s really fun and educational. It also proves the point that no data that your app doesn&amp;rsquo;t encrypt itself is safe in there from any app that hasn&amp;rsquo;t agreed to stay in its sandbox. (Annual reminder, don&amp;rsquo;t do your banking on your dev machine, folks.)&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;cd /Users/$YOUR_USERNAME/Library/Group\ Containers
ls -la 
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;At the top of the list will be a bunch of directories with a 10 character id code specific to the developer who created the app group. That&amp;rsquo;s what Lines will get on the Mac, too.&lt;/p&gt;
&lt;p&gt;On provisionedOS our App Group name will start with &lt;code&gt;group&lt;/code&gt;  It looks like specially signed macOS Apps can use &lt;code&gt;group&lt;/code&gt; names (Apple&amp;rsquo;s do) but when I tried to use them I kept getting &lt;code&gt;CFPrefsPlistSource&lt;/code&gt;/&lt;code&gt;kCFPreferencesAnyUser&lt;/code&gt; related errors. The only thing that resolved those for me was&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;separate entitlement files for all the targets (which we&amp;rsquo;ve done)&lt;/li&gt;
&lt;li&gt;separate App Group names for iOS and macOS&lt;/li&gt;
&lt;li&gt;macOS names that didn&amp;rsquo;t mimic ones registered to my developer account&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;App Group names get made most easily in Xcode in the Signing &amp;amp; Capabilities area. Hit the &amp;quot; + Capability &amp;quot; button and a dialog with all the options will pop up. Select App Groups. If the active target has both provisionedOS and macOS SDKs enabled in &amp;ldquo;Supported Destinations&amp;rdquo;, AppGroup will be listed twice as a capability to add.&lt;/p&gt;
&lt;p&gt;Stop.&lt;/p&gt;
&lt;p&gt;Go back to the &amp;ldquo;General&amp;rdquo; tab. Make sure that one &lt;code&gt;Lines&lt;/code&gt;/&lt;code&gt;LineGrabber&lt;/code&gt; target pair has ONLY macOS selected as an SDK under &amp;ldquo;Supported Destinations&amp;rdquo; and the other has the rest you&amp;rsquo;d like to support. Do not skip this step.&lt;/p&gt;
&lt;p&gt;Once the capability has been added to the target the &lt;code&gt;App Groups&lt;/code&gt; section appears. A &lt;code&gt;+&lt;/code&gt; button again allows for the creation of a new App Group. In the provisionedOS target, a check-box-bulleted list of existing app groups registered with your developer account comes along too.&lt;/p&gt;
&lt;p&gt;If making a new app group, in the macOS area the &lt;code&gt;$(TeamIdentifierPrefix)&lt;/code&gt; will be in the text field waiting for you. Xcode will also add the &lt;code&gt;.&lt;/code&gt;, so just put the first character next to the &lt;code&gt;)&lt;/code&gt;. In the provisionedOS target Xcode will prepend &lt;code&gt;group.&lt;/code&gt; and inform you that creating this new group will add it to the developer account.&lt;/p&gt;
&lt;p&gt;A target can be in more than one App Group. It just can&amp;rsquo;t be in both &lt;code&gt;group.&lt;/code&gt; prefixed and team identifier prefixed app groups at the same time.&lt;/p&gt;
&lt;p&gt;To help the project use these app groups I made an &lt;code&gt;AppGroupSettings&lt;/code&gt; enum that conditionally compiles like with &lt;a href=&#34;https://whynotestflight.com/excuses/what-if-i-just-copy-paste-from-the-web/#switcher-view&#34;&gt;the views&lt;/a&gt;. This code doesn&amp;rsquo;t work on Linux AT ALL anyway so the macOS or no distinction works well enough.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;enum&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;AppGroupSettings&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#if&lt;/span&gt; &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;os&lt;/span&gt;(&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;macOS&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;id&lt;/span&gt; = &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;KH3G9PXA68.com.carlynorama.lines&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#else&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;id&lt;/span&gt; = &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;group.com.carlynorama.safariextensionland&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#endif&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;semessageservice&#34;&gt;SEMessageService&lt;/h2&gt;
&lt;p&gt;So what code even uses these IDs?&lt;/p&gt;
&lt;p&gt;I made the scaffold for a &lt;a href=&#34;https://en.wikipedia.org/wiki/Duplex_(telecommunications)#FULL-DUPLEX&#34;&gt;full duplex&lt;/a&gt; &lt;a href=&#34;https://en.wikipedia.org/wiki/Communication_protocol&#34;&gt;protocol&lt;/a&gt; between the web extension&amp;rsquo;s &amp;ldquo;Native&amp;rdquo; part (&lt;code&gt;LineGrabber&lt;/code&gt;) and the parent or &amp;ldquo;Shell&amp;rdquo; app (&lt;code&gt;Lines&lt;/code&gt;). There&amp;rsquo;s a UserDefault bucket for &lt;code&gt;Lines&lt;/code&gt; to drop info into and a bucket for &lt;code&gt;LineGrabber&lt;/code&gt; to drop info into. While technically nothing in this code prevents them from dropping values into the other&amp;rsquo;s bucket, hopefully the function names will help prevent mistakes.&lt;/p&gt;
&lt;p&gt;NOTE: Keep an eye on what targets&amp;rsquo;s each Swift file belong to. The SEMessageService containing files need to belong to ALL FOUR.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//  SEMessageService.swift&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//  Lines&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//  Created by Carlyn Maw on 2/10/24.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;Foundation&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;protocol&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;SEMessageService&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;fromExtensionKey&lt;/span&gt;: &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt; { &lt;span style=&#34;color:#c6a0f6&#34;&gt;get&lt;/span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;fromShellKey&lt;/span&gt;: &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt; { &lt;span style=&#34;color:#c6a0f6&#34;&gt;get&lt;/span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;setFromExtensionMessage&lt;/span&gt;(to:some StringProtocol)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;getFromExtensionMessage&lt;/span&gt;() -&amp;gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;?
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;setFromShellMessage&lt;/span&gt;(to:some StringProtocol)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;getFromShellMessage&lt;/span&gt;() -&amp;gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;?
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;AppGroupService&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;private&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;appGroupID&lt;/span&gt;: &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;private&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;userDefaults&lt;/span&gt;: UserDefaults
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;containerURL&lt;/span&gt;:URL? {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        FileManager.&lt;span style=&#34;color:#c6a0f6&#34;&gt;default&lt;/span&gt;.containerURL(forSecurityApplicationGroupIdentifier:appGroupID)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;private&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;dumpUserDefaults&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(userDefaults.dictionaryRepresentation())
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;private&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;stringForKey&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; key:some StringProtocol) -&amp;gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;? {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        userDefaults.string(forKey: key &lt;span style=&#34;color:#c6a0f6&#34;&gt;as&lt;/span&gt;! &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;) &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//as? String&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;private&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;setString&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; value: some StringProtocol, forKey key: some StringProtocol) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        userDefaults.&lt;span style=&#34;color:#c6a0f6&#34;&gt;set&lt;/span&gt;(value &lt;span style=&#34;color:#c6a0f6&#34;&gt;as&lt;/span&gt;! &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;, forKey: key &lt;span style=&#34;color:#c6a0f6&#34;&gt;as&lt;/span&gt;! &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;private&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;allDefaults&lt;/span&gt;() -&amp;gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;Dictionary&lt;/span&gt;&amp;lt;&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;, &lt;span style=&#34;color:#91d7e3&#34;&gt;Any&lt;/span&gt;&amp;gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        userDefaults.dictionaryRepresentation()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;private&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;removeKey&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; key: some StringProtocol) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        userDefaults.removeObject(forKey: key &lt;span style=&#34;color:#c6a0f6&#34;&gt;as&lt;/span&gt;! &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//for sharedContainerIdentifier if needed.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;private&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;storageLocation&lt;/span&gt;:URL? {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        FileManager.&lt;span style=&#34;color:#c6a0f6&#34;&gt;default&lt;/span&gt;.containerURL(forSecurityApplicationGroupIdentifier:appGroupID)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;extension&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;AppGroupService&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;init&lt;/span&gt;?(appGroupID: &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;.appGroupID = appGroupID
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;guard&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;userDefs&lt;/span&gt; = UserDefaults(suiteName: appGroupID) &lt;span style=&#34;color:#c6a0f6&#34;&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;nil&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;.userDefaults = userDefs
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;extension&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;AppGroupService&lt;/span&gt;:SEMessageService {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;fromExtensionKey&lt;/span&gt;:&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt; { &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;toShell&amp;#34;&lt;/span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;fromShellKey&lt;/span&gt;:&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt; { &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;toExtension&amp;#34;&lt;/span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;setFromExtensionMessage&lt;/span&gt;(to message: some StringProtocol) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        setString(message, forKey:fromExtensionKey)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;getFromExtensionMessage&lt;/span&gt;() -&amp;gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;? {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        setString(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;test&amp;#34;&lt;/span&gt;, forKey: fromShellKey)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; stringForKey(fromExtensionKey)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;setFromShellMessage&lt;/span&gt;(to message: some StringProtocol) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        setString(message, forKey:fromShellKey)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;getFromShellMessage&lt;/span&gt;() -&amp;gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;? {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        stringForKey(fromShellKey)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;I&amp;rsquo;ve put a SEMessageService Protocol around the AppGroupService in case at some point I replace the AppGroup / UserDefaults style of communication with something else.&lt;/p&gt;
&lt;h3 id=&#34;code-in-linegrabber&#34;&gt;Code in LineGrabber&lt;/h3&gt;
&lt;h4 id=&#34;in-safariwebextensionhandler&#34;&gt;In SafariWebExtensionHandler&lt;/h4&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;shellMessageService&lt;/span&gt; = AppGroupService(appGroupID: AppGroupSettings.id)&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;!&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;setMessageForApp&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; message:&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        shellMessageService.setFromExtensionMessage(to: message)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;confirmMessageForApp&lt;/span&gt;() -&amp;gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        shellMessageService.getFromExtensionMessage() ?? &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;No Message&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;udKey&lt;/span&gt;:&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        shellMessageService.fromExtensionKey
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h4 id=&#34;inside-beginrequest-function&#34;&gt;Inside beginRequest function&lt;/h4&gt;
&lt;p&gt;&lt;code&gt;beginRequest&lt;/code&gt; has been restructured to use a &lt;code&gt;defer&lt;/code&gt; to send a response dictionary that&amp;rsquo;s been collecting reply messages along the way. It also uses a new key that wasn&amp;rsquo;t in the javascript before to detect if its&amp;rsquo; time to update the UserDefaults.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;beginRequest&lt;/span&gt;(with context: NSExtensionContext) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;responseContent&lt;/span&gt;: [ &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt; : &lt;span style=&#34;color:#91d7e3&#34;&gt;Any&lt;/span&gt; ] = [ : ]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;defer&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;response&lt;/span&gt; = NSExtensionItem()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            response.userInfo = [ SFExtensionMessageKey: responseContent ]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            context.completeRequest(returningItems: [ response ], completionHandler: &lt;span style=&#34;color:#f5a97f&#34;&gt;nil&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;       &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//... NO CHANGE&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;messageDictionary&lt;/span&gt; = message &lt;span style=&#34;color:#c6a0f6&#34;&gt;as&lt;/span&gt;? &lt;span style=&#34;color:#91d7e3&#34;&gt;Dictionary&lt;/span&gt;&amp;lt;&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;,&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;&amp;gt; {&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;!&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;_&lt;/span&gt; = messageDictionary[&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;isClip&amp;#34;&lt;/span&gt;] {  &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// &amp;lt;===== NEW KEY&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                responseContent[&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;receivedClip&amp;#34;&lt;/span&gt;] = &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;true&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                setMessageForApp(messageDictionary[&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;message&amp;#34;&lt;/span&gt;]&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;!&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                responseContent[&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;updatedForKey&amp;#34;&lt;/span&gt;] = udKey
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                responseContent[&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;updatedWith&amp;#34;&lt;/span&gt;] = confirmMessageForApp()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        responseContent[&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;echo&amp;#34;&lt;/span&gt;] = message
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The very first version of this code used&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;       if let myMessage = message as? String, myMessage.contains(&amp;#34;|&amp;#34;) { }
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;catch a message with a potential line in it. And it did work. However, I want to transition this code away from string parsing to object decoding so I added one line to &lt;code&gt;background.sendNewClip&lt;/code&gt; over in the extension javascript from &lt;a href=&#34;https://whynotestflight.com/excuses/how-do-you-get-messages-to-swift-directly/#sendNewClip&#34;&gt;what was there last post&lt;/a&gt;.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-js&#34; data-lang=&#34;js&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;function&lt;/span&gt; sendNewClip(message) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    console.log(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;something else&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;const&lt;/span&gt; nSend &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; browser.runtime.sendNativeMessage(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;application.id&amp;#34;&lt;/span&gt;, {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        message&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;:&lt;/span&gt; message, 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        isClip&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;true&amp;#34;&lt;/span&gt;  &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//&amp;lt;========= NEW LINE
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;    },
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;function&lt;/span&gt;(response) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            console.log(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Received newClip response:&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            console.log(response);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    );
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    nSend
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;It doesn&amp;rsquo;t actually even matter what value the &lt;code&gt;isClip&lt;/code&gt; key holds at this stage. That it&amp;rsquo;s in there at all creates the right flag for now.&lt;/p&gt;
&lt;h2 id=&#34;code-in-lines&#34;&gt;Code in Lines&lt;/h2&gt;
&lt;p&gt;Getting the new line out the UserDefaults was easy.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;ExtensionManager&lt;/span&gt;:ObservableObject {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;extensionMessageService&lt;/span&gt;:SEMessageService = AppGroupService(appGroupID: AppGroupSettings.id)&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;!&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;getExtensionMessage&lt;/span&gt;() -&amp;gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;? {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        extensionMessageService.getFromExtensionMessage()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    ...
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Getting the new line into the Lines array and then updating the UI took a few more changes.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;@State var Lines:[Line]&lt;/code&gt; got upgraded to a&lt;/p&gt;
&lt;p&gt;&lt;code&gt;@ObservedObject var myLines = LinesVM(lines: Lines())&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://developer.apple.com/documentation/swiftui/migrating-from-the-observable-object-protocol-to-the-observable-macro&#34;&gt;Switching to the new macro&lt;/a&gt; will come later.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;Foundation&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;SwiftUI&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;LinesVM&lt;/span&gt;:ObservableObject {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    @Published &lt;span style=&#34;color:#ed8796&#34;&gt;private&lt;/span&gt;(&lt;span style=&#34;color:#c6a0f6&#34;&gt;set&lt;/span&gt;) &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;lines&lt;/span&gt;:Lines
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;init&lt;/span&gt;(lines:Lines = Lines()) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;.lines = lines
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    @discardableResult
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;append&lt;/span&gt;(possibleLine:&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;) async -&amp;gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;Bool&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        await MainActor.run {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;before&lt;/span&gt; = lines.&lt;span style=&#34;color:#91d7e3&#34;&gt;count&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            lines.append(possibleLine: possibleLine)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; before &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;+&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;1&lt;/span&gt; == lines.&lt;span style=&#34;color:#91d7e3&#34;&gt;count&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;updateOrWarn&lt;/span&gt;(input:&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;?) async -&amp;gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; input &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;!=&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;nil&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;appendTask&lt;/span&gt; = await &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;.append(possibleLine:input!)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; appendTask ? &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Success&amp;#34;&lt;/span&gt; : &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Failed to add line text:&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;input!&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        } &lt;span style=&#34;color:#c6a0f6&#34;&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;No message waiting.&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;and &lt;code&gt;ExtesnionInfoView&lt;/code&gt; needed a new &lt;a href=&#34;https://www.hackingwithswift.com/quick-start/swiftui/how-to-use-environmentobject-to-share-data-between-views&#34;&gt;EnvironmentObject&lt;/a&gt; to handle the button that drives &lt;code&gt;Lines&lt;/code&gt; to go looking for changes.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;SwiftUI&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;ExtensionInfoView&lt;/span&gt;: View {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;extensionInfo&lt;/span&gt; = ExtensionManager()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    @EnvironmentObject &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;myLines&lt;/span&gt;:LinesVM
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    @State &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;statusText&lt;/span&gt; = &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;body&lt;/span&gt;: some View {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        VStack {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#if&lt;/span&gt; &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;os&lt;/span&gt;(&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;macOS&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            macExtInfoView().environmentObject(extensionInfo)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#else&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            iOSExtInfoView().environmentObject(extensionInfo)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#endif&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            Text(statusText)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            Button(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Load Latest&amp;#34;&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                loadLatest()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;loadLatest&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        statusText = &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;checking for lines...&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        Task {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            statusText = await myLines.updateOrWarn(input: extensionInfo.getExtensionMessage())
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;summary&#34;&gt;Summary&lt;/h2&gt;
&lt;p&gt;both macOS and iOS have a new button in the ExtensionInfoView that acts like the paste button in that, when the user clicks, the line will appear on the screen. Parity achieved.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;combined_newlinks.png&#34; alt=&#34;combined screenshot of both the macOS and iOS Lines app with a focus on the new &amp;ldquo;load latest&amp;rdquo; link&#34;&gt;&lt;/p&gt;
</description>
    </item>
    
    
    
    <item>
      <title>How do you get messages to Swift directly?</title>
      <link>https://whynotestflight.com/excuses/how-do-you-get-messages-to-swift-directly/</link>
      <pubDate>Sun, 11 Feb 2024 00:00:00 +0000</pubDate>
      
      <guid>https://whynotestflight.com/excuses/how-do-you-get-messages-to-swift-directly/</guid>
      <description>&lt;h2 id=&#34;relevant-repo&#34;&gt;Relevant Repo&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Lines &lt;a href=&#34;https://github.com/carlynorama/lines&#34;&gt;https://github.com/carlynorama/lines&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;relevant tags: hello-native-messaging, native-gets-the-clip&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;intro&#34;&gt;Intro&lt;/h2&gt;
&lt;p&gt;&lt;a href=&#34;https://whynotestflight.com/excuses/what-if-i-just-copy-paste-from-the-web/&#34;&gt;Last time&lt;/a&gt; left off with a web extension that was mostly boilerplate still but had a copy paste feature added to the &lt;code&gt;content.js&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;This time we&amp;rsquo;ll get it talking to the the &amp;ldquo;&lt;code&gt;Native App&lt;/code&gt;&amp;rdquo;, or the &lt;code&gt;Safari App Extension&lt;/code&gt; piece of the &lt;a href=&#34;https://whynotestflight.com/excuses/getting-started-with-safari-web-extensions/&#34;&gt;trifecta&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;changes-to-the-content-script&#34;&gt;Changes to the content script&lt;/h2&gt;
&lt;p&gt;Mozilla again comes to the rescue with example code to &lt;a href=&#34;https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/runtime/sendMessage&#34;&gt;notify the background based on a click&lt;/a&gt; from a content script. I adapted it to be called from the copying function &lt;a href=&#34;https://whynotestflight.com/excuses/what-if-i-just-copy-paste-from-the-web/#content-script&#34;&gt;added last time&lt;/a&gt;. The call to &lt;code&gt;notifyBackgroundPage&lt;/code&gt; goes before or after the call to  &lt;code&gt;updateClipboard&lt;/code&gt;. They&amp;rsquo;re independent features at this point.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;function handleResponse(message) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    console.log(`Message from the background script: &lt;span style=&#34;color:#ed8796&#34;&gt;$&lt;/span&gt;{message}`);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  function handleError(error) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    console.log(`Error: &lt;span style=&#34;color:#ed8796&#34;&gt;$&lt;/span&gt;{error}`);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  function notifyBackgroundPage(message) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    const sending = browser.runtime.sendMessage({
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      greeting: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;newClip&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      message: message
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    });
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    sending.then(handleResponse, handleError);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;changes-to-manifest-file-and-background-script&#34;&gt;Changes to manifest file and background script&lt;/h2&gt;
&lt;h3 id=&#34;native-messaging-hello-world&#34;&gt;Native Messaging Hello World&lt;/h3&gt;
&lt;p&gt;When a web extension calls the part of the extension that lives outside the browser, like the password storage of a password manager the API calls it &lt;a href=&#34;https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/Native_messaging&#34;&gt;Native messaging&lt;/a&gt;. For us that&amp;rsquo;s the part in Swift and found in the LineGrabber targets.&lt;/p&gt;
&lt;p&gt;Non-Safari web extensions have an additional manifest file to explain to the browser how to relate to this &amp;ldquo;native app.&amp;rdquo; That&amp;rsquo;s taken care of by &lt;code&gt;Safari Services&lt;/code&gt; for Safari Web Extensions.&lt;/p&gt;
&lt;p&gt;First, update the permissions in our extension&amp;rsquo;s manifest.json to add the &amp;ldquo;nativeMessaging&amp;rdquo; permission.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-json&#34; data-lang=&#34;json&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;permissions&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;:&lt;/span&gt; [ &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;activeTab&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;scripting&amp;#34;&lt;/span&gt;,  &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;clipboardWrite&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;nativeMessaging&amp;#34;&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The below is &lt;a href=&#34;https://developer.apple.com/documentation/safariservices/safari_web_extensions/messaging_a_web_extension_s_native_app&#34;&gt;demo code&lt;/a&gt; from Apple&amp;rsquo;s  that was shown in WWDC20&amp;rsquo;s &lt;a href=&#34;https://developer.apple.com/videos/play/wwdc2020/10665/&#34;&gt;10665: Meet Safari Web Extensions&lt;/a&gt;. It works perfectly with the the boilerplate &lt;code&gt;SafariWebExtensionHandler&lt;/code&gt; from the basic Safari App Extension from the &lt;code&gt;File &amp;gt; New &amp;gt; Target&lt;/code&gt; dialog.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//Use runtime.onMessageExternal to talk to other extensions or websites&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;browser.runtime.sendNativeMessage(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;application.id&amp;#34;&lt;/span&gt;, {message: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Hello from background page&amp;#34;&lt;/span&gt;}, function(response) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    console.log(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Received sendNativeMessage response:&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    console.log(response);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;});
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// Set up a connection to receive messages from the native app.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;port&lt;/span&gt; = browser.runtime.connectNative(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;application.id&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;port.postMessage(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Hello from JavaScript Port&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;port.onMessage.addListener(function(message) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    console.log(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Received native port message:&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    console.log(message);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;});
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;port.onDisconnect.addListener(function(disconnectedPort) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    console.log(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Received native port disconnect:&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    console.log(disconnectedPort);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;});
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Confirm this works by:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;rebuilding the extension app (CMD+B)&lt;/li&gt;
&lt;li&gt;opening a webpage that has permission to run the extension&lt;/li&gt;
&lt;li&gt;having both:
&lt;ul&gt;
&lt;li&gt;the console of the page (OPT+CMD+C or the Develop menu for the Simulator) open&lt;/li&gt;
&lt;li&gt;the console for background script open &lt;code&gt;Develop &amp;gt; Web Extension Background Content &amp;gt; YOUR EXTENSION NAME&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The messages should be being passed around. Make sure to open the objects in the console to look at them.&lt;/p&gt;
&lt;h2 id=&#34;the-javascript-demo-code-line-by-line&#34;&gt;The Javascript Demo Code Line by Line&lt;/h2&gt;
&lt;h3 id=&#34;sendnativemessage&#34;&gt;sendNativeMessage&lt;/h3&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-javascript&#34; data-lang=&#34;javascript&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;browser.runtime.sendNativeMessage(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;application.id&amp;#34;&lt;/span&gt;, {message&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Hello from background page&amp;#34;&lt;/span&gt;}, &lt;span style=&#34;color:#ed8796&#34;&gt;function&lt;/span&gt;(response) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    console.log(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Received sendNativeMessage response:&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    console.log(response);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;});
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;a href=&#34;https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/runtime/sendNativeMessage&#34;&gt;&lt;code&gt;browser.runtime.sendNativeMessage&lt;/code&gt;&lt;/a&gt; is asynchronous code. The demo code uses an older callback style.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;application&lt;/strong&gt;: A string, &amp;ldquo;application.id&amp;rdquo; used to determine who the native app is, Safari replaces this for us with the right info behind the scenes. It&amp;rsquo;s supposed to be the same name as in the &lt;em&gt;Application&amp;rsquo;s&lt;/em&gt; manifest.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;message&lt;/strong&gt;: An object, provided as the JSON {message: &amp;ldquo;Hello from background page&amp;rdquo;}&lt;/li&gt;
&lt;li&gt;a function to handle the response.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Mozilla provides newer Promise-style example calls on the website linked to above.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-javascript&#34; data-lang=&#34;javascript&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//ping_pong is the app name and &amp;#34;ping&amp;#34; is the message. 
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;  &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; sending &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; browser.runtime.sendNativeMessage(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;ping_pong&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;ping&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  sending.then(onResponse, onError);
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;connectnativemessage&#34;&gt;connectNativeMessage&lt;/h3&gt;
&lt;p&gt;&lt;a href=&#34;https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/runtime/connectNative&#34;&gt;&lt;code&gt;browser.runtime.connectNative&lt;/code&gt;&lt;/a&gt; opens the two way street which can send or receive messages called a &lt;a href=&#34;https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/runtime/Port&#34;&gt;Port&lt;/a&gt;&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-javascript&#34; data-lang=&#34;javascript&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; port &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; browser.runtime.connectNative(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;application.id&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Like with sendNative message, Safari handles replacing &amp;ldquo;application.id&amp;rdquo; for us.&lt;/p&gt;
&lt;h4 id=&#34;send-a-message&#34;&gt;Send a message&lt;/h4&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-javascript&#34; data-lang=&#34;javascript&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;port.postMessage(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Hello from JavaScript Port&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h4 id=&#34;add-an-event-listener-to-handle-messages&#34;&gt;Add an event listener to handle messages&lt;/h4&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-javascript&#34; data-lang=&#34;javascript&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;port.onMessage.addListener(&lt;span style=&#34;color:#ed8796&#34;&gt;function&lt;/span&gt;(message) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    console.log(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Received native port message:&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    console.log(message);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;});
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;could be rewritten as&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-javascript&#34; data-lang=&#34;javascript&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; messageHandler &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; (message) =&amp;gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    console.log(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Received native port message:&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    console.log(message);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;port.onMessage.addListener(messageHandler);
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Note: if a function is written as an &lt;a href=&#34;https://en.wikipedia.org/wiki/Expression_(computer_science)&#34;&gt;expression&lt;/a&gt; like it is here, the function does not get &lt;a href=&#34;https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function#Function_declaration_hoisting&#34;&gt;hoisted&lt;/a&gt; like it does as a &lt;a href=&#34;https://en.wikipedia.org/wiki/Statement_(computer_science)&#34;&gt;statement&lt;/a&gt;. The expression must be defined BEFORE the call site.&lt;/p&gt;
&lt;h4 id=&#34;disconnect&#34;&gt;Disconnect&lt;/h4&gt;
&lt;p&gt;It would be a good idea to read up on the port &lt;a href=&#34;https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/Runtime/Port#lifecycle&#34;&gt;lifecycle&lt;/a&gt; to see how ports handle themselves in general. When done communicating, closing the port has no side effects in Chrome/Chromium browsers, but in Firefox that closes the port even if other listeners still need it. TODO: What happens in WebKit?&lt;/p&gt;
&lt;p&gt;This&lt;code&gt;onDisconnect&lt;/code&gt; code takes a function expression inside the closure, which is yet another pattern.&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;port.onDisconnect.addListener((p) =&amp;gt; {
    console.log(&amp;#34;Received native port disconnect:&amp;#34;);
    console.log(p);
    if (p.error) {  //runtime.lastError in chrome
        console.log(`Disconnected due to an error: ${p.error.message}`);
    }
});
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&#34;changes-to-the-background-script&#34;&gt;Changes to the background script&lt;/h2&gt;
&lt;p id=&#34;sendNewClip&#34;&gt;The content script dutifully sends the clip along. Our background script sends a messages. But the background script doesn&amp;rsquo;t send THAT message. After understanding the demo code it becomes clearer how to add a new function to send a message containing the clipboard. It can be trigger it from the background.js &lt;code&gt;runtime.onMessage&lt;/code&gt; listener when it gets that new clip.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-js&#34; data-lang=&#34;js&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;function&lt;/span&gt; sendNewClip(message) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    console.log(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;something else&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;const&lt;/span&gt; nSend &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; browser.runtime.sendNativeMessage(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;application.id&amp;#34;&lt;/span&gt;, {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        message&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;:&lt;/span&gt; message
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    },
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;function&lt;/span&gt;(response) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            console.log(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Received newClip response:&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            console.log(response);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    );
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    nSend
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;browser.runtime.onMessage.addListener((request, sender, sendResponse) =&amp;gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    console.log(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Received request: &amp;#34;&lt;/span&gt;, request);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; (request.greeting &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;===&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;hello&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        sendResponse({ farewell&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;goodbye&amp;#34;&lt;/span&gt; });
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; (request.greeting &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;===&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;newClip&amp;#34;&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        console.log(request.message);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        sendNewClip(request.message);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//sendResponse({ farewell: &amp;#34;goodbye&amp;#34; });
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;});
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;console.log(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;hello from background.js&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;the-swift-demo-code-line-by-line&#34;&gt;The Swift Demo Code Line by Line&lt;/h2&gt;
&lt;p&gt;All of our Safari Web Extension code lives in &lt;code&gt;SafariWebExtensionHandler&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Take the time to look into both of the &lt;code&gt;Info.plist&lt;/code&gt; files for the extension targets. The line item for &lt;a href=&#34;https://developer.apple.com/documentation/bundleresources/information_property_list/nsextension/nsextensionprincipalclass/&#34;&gt;NSExtensionPrincipalClass&lt;/a&gt; has the value &lt;code&gt;$(PRODUCT_MODULE_NAME).SafariWebExtensionHandler&lt;/code&gt;. Moving the conformance to &lt;a href=&#34;https://developer.apple.com/documentation/foundation/nsextensionrequesthandling&#34;&gt;NSExtensionRequestHandling&lt;/a&gt; to a different class or renaming the class listed here means coming back the plist to make updates as well.&lt;/p&gt;
&lt;p&gt;Whatever the principal class ends up being, it will have the &lt;a href=&#34;https://developer.apple.com/documentation/foundation/nsextensionrequesthandling/1413395-beginrequest/&#34;&gt;&lt;code&gt;beginRequest&lt;/code&gt;&lt;/a&gt; function which handles communication with Safari. The &lt;code&gt;request&lt;/code&gt; is incoming from Safari not outgoing from our code, but our code can provide responses.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;beginRequest&lt;/span&gt;(with context: NSExtensionContext) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;request&lt;/span&gt; = context.inputItems.&lt;span style=&#34;color:#91d7e3&#34;&gt;first&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;as&lt;/span&gt;? NSExtensionItem
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The &lt;a href=&#34;https://developer.apple.com/documentation/foundation/nsextensioncontext&#34;&gt;NSExtensionContext&lt;/a&gt; gets created by SafariServices using the extension&amp;rsquo;s id and the native app&amp;rsquo;s id. This context has a list of input items and we&amp;rsquo;re just going to skim the first off the top and keep our fingers crossed it can be cast as a &lt;a href=&#34;https://developer.apple.com/documentation/foundation/nsextensionitem/&#34;&gt;NSExtensionItem&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Among a couple other things the &lt;code&gt;request&lt;/code&gt; might have &lt;a href=&#34;https://developer.apple.com/documentation/foundation/nsextensionitem/1414953-userinfo&#34;&gt;userInfo&lt;/a&gt;([AnyHashable : Any]) or &lt;a href=&#34;https://developer.apple.com/documentation/foundation/nsextensionitem/1416690-attachments&#34;&gt;attachments&lt;/a&gt;(&lt;a href=&#34;https://developer.apple.com/documentation/foundation/nsitemprovider&#34;&gt;NSProvider&lt;/a&gt;). A lot of hopeful casting goes on in this neck of the code. The Lines app example relies primarily on &lt;code&gt;Strings&lt;/code&gt;, but this (older?) example from Hacking With Swift &lt;a href=&#34;https://www.hackingwithswift.com/read/19/overview&#34;&gt;uses images&lt;/a&gt;.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;profile&lt;/span&gt;: UUID?
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#available&lt;/span&gt;(&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;iOS&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;17.0&lt;/span&gt;, &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;macOS&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;14.0&lt;/span&gt;, &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;*&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            profile = request?.userInfo?[SFExtensionProfileKey] &lt;span style=&#34;color:#c6a0f6&#34;&gt;as&lt;/span&gt;? UUID
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        } &lt;span style=&#34;color:#c6a0f6&#34;&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            profile = request?.userInfo?[&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;profile&amp;#34;&lt;/span&gt;] &lt;span style=&#34;color:#c6a0f6&#34;&gt;as&lt;/span&gt;? UUID
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Is the profile information in the &lt;code&gt;userInfo&lt;/code&gt; dictionary? Safari puts some in there and &lt;a href=&#34;https://developer.apple.com/documentation/safariservices/sfextensionprofilekey&#34;&gt;&lt;code&gt;SFExtensionProfileKey&lt;/code&gt;&lt;/a&gt; contains a default key to get it out.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;message&lt;/span&gt;: &lt;span style=&#34;color:#91d7e3&#34;&gt;Any&lt;/span&gt;?
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#available&lt;/span&gt;(&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;iOS&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;17.0&lt;/span&gt;, &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;macOS&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;14.0&lt;/span&gt;, &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;*&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            message = request?.userInfo?[SFExtensionMessageKey]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        } &lt;span style=&#34;color:#c6a0f6&#34;&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            message = request?.userInfo?[&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;message&amp;#34;&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Is there a message? Safari puts that in there too and &lt;a href=&#34;https://developer.apple.com/documentation/safariservices/sfextensionmessagekey&#34;&gt;SFExtensionMessageKey&lt;/a&gt; contains a default key.&lt;/p&gt;
&lt;p&gt;Safari uses these keys assuming you will too. Any messages packaged up by the native messaging code end up under this key.  The value of this key does NOT appear in the extension&amp;rsquo;s javascript from what I can tell.&lt;/p&gt;
&lt;p&gt;Changing background.js to&amp;hellip;&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-javascript&#34; data-lang=&#34;javascript&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;...runtime.sendNativeMessage(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;application.id&amp;#34;&lt;/span&gt;, {kumquat&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Hello from background page&amp;#34;&lt;/span&gt;}, functi...)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&amp;hellip;doesn&amp;rsquo;t change how it works. The &lt;a href=&#34;https://developer.apple.com/documentation/safariservices/sfextensionmessagekey&#34;&gt;SFExtensionMessageKey&lt;/a&gt; is the name given by Safari &amp;amp; the Web Extension API to that position of the arguments when it packages them up, not the key inside the object. That&amp;rsquo;s up to your code.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        os_log(.&lt;span style=&#34;color:#c6a0f6&#34;&gt;default&lt;/span&gt;, &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Received message from browser.runtime.sendNativeMessage: %@ (profile: %@)&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;(describing: message), profile?.uuidString ?? &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;none&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;App Extension have a separate context from the Shell app. Print statements and debug logs do not appear in Xcode&amp;rsquo;s console when they run, as far as I&amp;rsquo;ve been able to tell. Additionally I have never been able to find this log message in the Console App. Which is not to say it isn&amp;rsquo;t there, I&amp;rsquo;m just a Console App rube. Logging will be switched to &lt;a href=&#34;https://developer.apple.com/documentation/os/logger&#34;&gt;Logger&lt;/a&gt; soon.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;response&lt;/span&gt; = NSExtensionItem()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        response.userInfo = [ SFExtensionMessageKey: [ &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;echo&amp;#34;&lt;/span&gt;: message ] ]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        context.completeRequest(returningItems: [ response ], completionHandler: &lt;span style=&#34;color:#f5a97f&#34;&gt;nil&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The example response dictionary just echos back the received message. I&amp;rsquo;ve found it useful for debugging so I&amp;rsquo;ve left it in.&lt;/p&gt;
&lt;h2 id=&#34;summary&#34;&gt;Summary&lt;/h2&gt;
&lt;p&gt;Native messaging comes together pretty easily with the demo code, but it took a minute to understand how exactly. The Safari Web Extension uses an XPC service under the hood, but its commingled with JavaScript on the other end. It will be interesting to keep them talking, but not tangled.  What we still haven&amp;rsquo;t is taken that one last step of adding&lt;/p&gt;
</description>
    </item>
    
    
    
    <item>
      <title>What if I just copy-paste from the web?</title>
      <link>https://whynotestflight.com/excuses/what-if-i-just-copy-paste-from-the-web/</link>
      <pubDate>Sat, 10 Feb 2024 00:00:00 +0000</pubDate>
      
      <guid>https://whynotestflight.com/excuses/what-if-i-just-copy-paste-from-the-web/</guid>
      <description>&lt;h2 id=&#34;related-repo&#34;&gt;Related Repo&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Lines &lt;a href=&#34;https://github.com/carlynorama/lines&#34;&gt;https://github.com/carlynorama/lines&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;relevant tags: TheBase, BasicExtensionEnabled, Copy-Paste-Style&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;intro&#34;&gt;Intro&lt;/h2&gt;
&lt;p&gt;As noted &lt;a href=&#34;https://whynotestflight.com/excuses/getting-started-with-safari-web-extensions/#option-2&#34;&gt;before&lt;/a&gt; Apple makes it very easy to create a Safari Web Extension if one already has an extension that works in another browser. Just run the command line tool. Done. If starting from nothing there&amp;rsquo;s even a starter app in the &lt;code&gt;New &amp;gt; Project&lt;/code&gt; dialog.&lt;/p&gt;
&lt;p&gt;If instead the idea is to augment an existing app that maybe doesn&amp;rsquo;t already have a online-service connected to it, how to handle getting the information from one sandbox to the other?&lt;/p&gt;
&lt;p&gt;One easy way would be to facilitate copying and pasting the information from the web to the original app.&lt;/p&gt;
&lt;p&gt;That can be done in just a handful of steps. Assuming knowledge of Swift and basic web development already, which maybe assuming a lot, but here we go.&lt;/p&gt;
&lt;h2 id=&#34;have-a-starting-app&#34;&gt;Have a starting app&lt;/h2&gt;
&lt;p&gt;Meet &lt;code&gt;Lines&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;This App works by loading a text file of lines into a view on start up. Each of the lines is a link that will take you to a URL where the citation comes from.&lt;/p&gt;
&lt;p&gt;The format of a &lt;code&gt;Line&lt;/code&gt; is very simplistic at rest in it&amp;rsquo;s text file:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;{string_part}|{url_part}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;img src=&#34;lines_basic.png&#34; alt=&#34;Screenshot of Lines. In Dark mode. It&amp;rsquo;s very plain, but it has an Aliens by Amy Lowell as the lines in it&#34;&gt;&lt;/p&gt;
&lt;h2 id=&#34;add-the-demo-extension&#34;&gt;Add the demo extension&lt;/h2&gt;
&lt;p&gt;Meet LineGrabber&lt;/p&gt;
&lt;p&gt;Because I want a macOS native app I split the original app into 2 targets, one for the iOS/iPadOs family and one for macOS. In addition, I added a single Safari App Extension Target, which got me all the demo files. I then copied that target as well. I made sure each target had its own entitlements file and the two extensions had their own info.plist files to be extra careful. Every target then needed the new file location information put into their &lt;a href=&#34;https://developer.apple.com/documentation/Xcode/configuring-the-build-settings-of-a-target&#34;&gt;build settings&lt;/a&gt;. (search for &amp;ldquo;entitlements&amp;rdquo; and &amp;ldquo;info.plist file&amp;rdquo;).&lt;/p&gt;
&lt;p&gt;The iOS/macOS split supports the differences in how AppGroups are handled. iOS &amp;amp; the Tablettes require a developer account to have an AppGroup. Mac Apps do not.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;lines_reorg.png&#34; alt=&#34;Screenshot of Xcode showing the reorganized files&#34;&gt;&lt;/p&gt;
&lt;p&gt;Right now the extension just has the default extension code, but it does get up and running on both platforms using SwiftUI in the shell app instead of the UIKit/WebKit boilerplate that comes in the full sample app.&lt;/p&gt;
&lt;p&gt;I wrote an ExtensionManager:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;Foundation&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;SafariServices&lt;/span&gt;.&lt;span style=&#34;color:#eed49f&#34;&gt;SFSafariApplication&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#if&lt;/span&gt; &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;os&lt;/span&gt;(&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;macOS&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;SafariServices&lt;/span&gt;.&lt;span style=&#34;color:#eed49f&#34;&gt;SFSafariExtensionManager&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#endif&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;os&lt;/span&gt;.&lt;span style=&#34;color:#eed49f&#34;&gt;log&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;ExtensionManager&lt;/span&gt;:ObservableObject {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#if&lt;/span&gt; &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;os&lt;/span&gt;(&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;macOS&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;isEnabled&lt;/span&gt; = &lt;span style=&#34;color:#f5a97f&#34;&gt;false&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;setExtensionStatus&lt;/span&gt;() async {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;do&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            isEnabled = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; await SFSafariExtensionManager.stateOfSafariExtension(withIdentifier: Constants.macBundleID).isEnabled
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        } &lt;span style=&#34;color:#c6a0f6&#34;&gt;catch&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            await NSApp.presentError(error)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;openSafariSettings&lt;/span&gt;() async {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;do&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; await SFSafariApplication.showPreferencesForExtension(withIdentifier: Constants.macBundleID)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//kills the app.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//If don&amp;#39;t kill the app, rewrite so view with status is flagged as stale somehow.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            await NSApplication.shared.terminate(&lt;span style=&#34;color:#f5a97f&#34;&gt;nil&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        } &lt;span style=&#34;color:#c6a0f6&#34;&gt;catch&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            await NSApp.presentError(error)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;sendBackgroundMessageToExtension&lt;/span&gt;(title:some StringProtocol, message:&lt;span style=&#34;color:#91d7e3&#34;&gt;Dictionary&lt;/span&gt;&amp;lt;&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;,&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;&amp;gt;) async {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;do&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; await dispatchMessage(title: title, message: message)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            os_log(.&lt;span style=&#34;color:#c6a0f6&#34;&gt;default&lt;/span&gt;, &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Dispatching message to the extension finished&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        } &lt;span style=&#34;color:#c6a0f6&#34;&gt;catch&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            os_log(.&lt;span style=&#34;color:#c6a0f6&#34;&gt;default&lt;/span&gt;, &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;error&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;sendBackgroundMessageToExtension&lt;/span&gt;(title:some StringProtocol, message:&lt;span style=&#34;color:#91d7e3&#34;&gt;Dictionary&lt;/span&gt;&amp;lt;&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;,&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;&amp;gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        SFSafariApplication.dispatchMessage(withName: title &lt;span style=&#34;color:#c6a0f6&#34;&gt;as&lt;/span&gt;! &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;, toExtensionWithIdentifier: Constants.macBundleID, userInfo: message) { (error) -&amp;gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;Void&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            os_log(.&lt;span style=&#34;color:#c6a0f6&#34;&gt;default&lt;/span&gt;, &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Dispatching message to the extension finished &lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;error&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;MARK:&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt; async wrappers on SFSafariApplication&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;dispatchMessage&lt;/span&gt;(title:some StringProtocol, message:&lt;span style=&#34;color:#91d7e3&#34;&gt;Dictionary&lt;/span&gt;&amp;lt;&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;,&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;&amp;gt;) async &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;result&lt;/span&gt; = await withCheckedContinuation { continuation &lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            SFSafariApplication.dispatchMessage(withName: title &lt;span style=&#34;color:#c6a0f6&#34;&gt;as&lt;/span&gt;! &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;, toExtensionWithIdentifier: Constants.macBundleID, userInfo: message) { messages &lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                continuation.resume(returning: messages)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; result &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;!=&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;nil&lt;/span&gt; { &lt;span style=&#34;color:#c6a0f6&#34;&gt;throw&lt;/span&gt; result! }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#endif&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p id=&#34;switcher-view&#34;&gt;That drives the part of the UI related to the extension:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;SwiftUI&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;ExtensionInfoView&lt;/span&gt;: View {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;extensionInfo&lt;/span&gt; = ExtensionManager()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;body&lt;/span&gt;: some View {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#if&lt;/span&gt; &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;os&lt;/span&gt;(&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;macOS&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        macExtInfoView().environmentObject(extensionInfo)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#else&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        iOSExtInfoView().environmentObject(extensionInfo)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#endif&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The iOS view&amp;hellip;&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;SwiftUI&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;iOSExtInfoView&lt;/span&gt;: View {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    @EnvironmentObject &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;viewModel&lt;/span&gt;:ExtensionManager
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;body&lt;/span&gt;: some View {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        VStack {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            HStack {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            Text(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Turn on the Safari extension &lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;Constants.extensionName&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt; in “Settings › Safari” to grab new lines.&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                .multilineTextAlignment(.center)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                .padding(.horizontal)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            Button(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Open Settings&amp;#34;&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// Get the settings URL and open it&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;url&lt;/span&gt; = URL(string: UIApplication.openSettingsURLString) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    UIApplication.shared.open(url)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;url&lt;/span&gt; = URL(string: Constants.goodSamplePage) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                Link(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Open Example page&amp;#34;&lt;/span&gt;, destination: url)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&amp;hellip; and the macOS view&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#if&lt;/span&gt; &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;os&lt;/span&gt;(&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;macOS&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;SwiftUI&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;macExtInfoView&lt;/span&gt;: View {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    @Environment(&lt;span style=&#34;color:#ed8796&#34;&gt;\&lt;/span&gt;.openURL) &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;openURL&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    @EnvironmentObject &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;viewModel&lt;/span&gt;:ExtensionManager
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    @State &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;enabledStatusText&lt;/span&gt;:&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt; = &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;body&lt;/span&gt;: some View {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        VStack {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;           
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            Text(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Extension is: &lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;enabledStatusText&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                .font(.title2)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                .lineLimit(&lt;span style=&#34;color:#f5a97f&#34;&gt;nil&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            Button(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Quit and Open Safari Settings&amp;#34;&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                Task {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    await viewModel.openSafariSettings()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            Button(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Open Example Page / openURL style&amp;#34;&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                openURL(URL(string: Constants.goodSamplePage)&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;!&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            Button(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Send Message To Extension&amp;#34;&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                 viewModel.sendBackgroundMessageToExtension(title: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;DemoMessage&amp;#34;&lt;/span&gt;, message: [&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Hello&amp;#34;&lt;/span&gt;:&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;World&amp;#34;&lt;/span&gt;])
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }.task {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            await viewModel.setExtensionStatus()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            enabledStatusText = viewModel.isEnabled ? &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;enabled&amp;#34;&lt;/span&gt; : &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;disabled&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&amp;hellip;have different capabilities. Notice how much more the macOS version can do at this stage. That&amp;rsquo;s because of the legacy of &lt;code&gt;SafariServices.SFSafariExtensionManager&lt;/code&gt;. The &lt;code&gt;Constants.macBundleID&lt;/code&gt; used in related functions is the bundle id of the extension target.  This id allows Safari to provide the needed &lt;a href=&#34;https://developer.apple.com/documentation/foundation/nsextensioncontext&#34;&gt;NSExtensionContext&lt;/a&gt; for the requests. Apple seems to want people to focus on building as much as possible using the JavaScript APIs to make the browser plugins as cross-platform portable as possible and I think that&amp;rsquo;s great. Double thumbs up. That&amp;rsquo;s what we&amp;rsquo;ll do.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;lines_withExtension.png&#34; alt=&#34;Screenshot of the macOS version of the Lines App, now with extension related details like whether the extension is enabled.&#34;&gt;&lt;/p&gt;
&lt;h2 id=&#34;update-the-javascript&#34;&gt;Update the JavaScript&lt;/h2&gt;
&lt;p&gt;At this point we only need to change two files.&lt;/p&gt;
&lt;h3 id=&#34;manifest-file&#34;&gt;Manifest File&lt;/h3&gt;
&lt;p&gt;manifest.json goes from&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-json&#34; data-lang=&#34;json&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;content_scripts&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;:&lt;/span&gt; [{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;&amp;#34;js&amp;#34;&lt;/span&gt;: [ &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;content.js&amp;#34;&lt;/span&gt; ],
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;23:&lt;/span&gt;      &lt;span style=&#34;color:#c6a0f6&#34;&gt;&amp;#34;matches&amp;#34;&lt;/span&gt;: [ &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;*://example.com/*&amp;#34;&lt;/span&gt; ]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }]&lt;span style=&#34;color:#ed8796&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f5a97f&#34;&gt;38&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;:&lt;/span&gt;   &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;permissions&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;:&lt;/span&gt; [ ]
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;to:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-json&#34; data-lang=&#34;json&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;content_scripts&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;:&lt;/span&gt; [{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;&amp;#34;js&amp;#34;&lt;/span&gt;: [ &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;content.js&amp;#34;&lt;/span&gt; ],
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;23:&lt;/span&gt;      &lt;span style=&#34;color:#c6a0f6&#34;&gt;&amp;#34;matches&amp;#34;&lt;/span&gt;: [ &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&amp;lt;all_urls&amp;gt;&amp;#34;&lt;/span&gt; ]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }]&lt;span style=&#34;color:#ed8796&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f5a97f&#34;&gt;38&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;:&lt;/span&gt;   &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;permissions&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;:&lt;/span&gt;  [ &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;activeTab&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;scripting&amp;#34;&lt;/span&gt;,  &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;clipboardWrite&amp;#34;&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Those changes mean that, once given permission, the extension will be able to inject scripts into any page and write its content to the clipboard as long as it&amp;rsquo;s the active tab.&lt;/p&gt;
&lt;h2 id=&#34;content-script&#34;&gt;Content Script&lt;/h2&gt;
&lt;p&gt;At this point it will do all of the script injecting from &lt;code&gt;content.js&lt;/code&gt;&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-JavaScript&#34; data-lang=&#34;JavaScript&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;console.log(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;hello from content.js&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//need other approach on FireFox..
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/Interact_with_the_clipboard
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;function&lt;/span&gt; updateClipboard(newClip) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    navigator.clipboard.writeText(newClip).then(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        () =&amp;gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            console.log(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;clipboard write success:&amp;#34;&lt;/span&gt;, newClip)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        },
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        () =&amp;gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            console.log(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;clipboard write failed:&amp;#34;&lt;/span&gt;, newClip)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        },
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    );
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; copyable &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;Array&lt;/span&gt;.from(&lt;span style=&#34;color:#91d7e3&#34;&gt;document&lt;/span&gt;.getElementsByTagName(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#39;p&amp;#39;&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;.concat(&lt;span style=&#34;color:#91d7e3&#34;&gt;Array&lt;/span&gt;.from(&lt;span style=&#34;color:#91d7e3&#34;&gt;document&lt;/span&gt;.getElementsByTagName(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#39;li&amp;#39;&lt;/span&gt;)));
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;for&lt;/span&gt;( &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; i &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;0&lt;/span&gt;; i &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;lt;&lt;/span&gt; copyable.length; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;++&lt;/span&gt;i ) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    copyable[i].onclick &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;function&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//This strips out all tags. If want something more attributed
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//strings friendly use .innerHTML or .innerText
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; text &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;this&lt;/span&gt;.textContent; &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//.innerHTML;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; url &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;document&lt;/span&gt;.location.href;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        updateClipboard(text &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;+&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;|&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;+&lt;/span&gt; url);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;As a reminder, the strings get stored in lines.txt as a string followed by a pipe character (&lt;code&gt;|&lt;/code&gt;), followed by a URL.&lt;/p&gt;
&lt;p&gt;This code gets every &lt;code&gt;&amp;lt;p&amp;gt;&lt;/code&gt; and &lt;code&gt;&amp;lt;li&amp;gt;&lt;/code&gt; from the &lt;a href=&#34;https://developer.mozilla.org/en-US/docs/Web/API/Document_Object_Model&#34;&gt;DOM&lt;/a&gt; and gives them all click listeners. When clicked, that text and the URL of the current open tab get bundled into the pasteboard in that same | delimited format the Lines App code uses.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;navigator.clipboard.writeText(newClip)&lt;/code&gt; is asynchronous and this code from the &lt;a href=&#34;(https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/Interact_with_the_clipboard)&#34;&gt;Mozilla&lt;/a&gt; foundation uses the &lt;a href=&#34;https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/then&#34;&gt;&lt;code&gt;Promise.prototype.then()&lt;/code&gt;&lt;/a&gt; syntax to provide the success and failure handlers. &lt;a href=&#34;https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise&#34;&gt;Promises&lt;/a&gt; have been widely adopted for asynchronous web extension API&amp;rsquo;s for &lt;a href=&#34;https://extensionworkshop.com/documentation/develop/manifest-v3-migration-guide/&#34;&gt;Manifest 3&lt;/a&gt;, &lt;a href=&#34;https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/Build_a_cross_browser_extension#api_asynchronous_event_handling&#34;&gt;Safari and Firefox even earlier&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Load a tab, open the console (CMD-OPT-C) and click away to see the log messages.&lt;/p&gt;
&lt;h2 id=&#34;swiftui-pastebutton&#34;&gt;SwiftUI PasteButton&lt;/h2&gt;
&lt;p&gt;The point is to bring this copied text back into the &lt;code&gt;Lines App&lt;/code&gt; proper, though. That&amp;rsquo;s easily accomplished in SwiftUI using the [&lt;code&gt;PasteButton&lt;/code&gt;][PB] introduced in this &lt;a href=&#34;https://developer.apple.com/wwdc22/10062?time=230&#34;&gt;WWDC22 video on Transferable&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;[PB]https://developer.apple.com/documentation/swiftui/pastebutton&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    PasteButton(payloadType: &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;.&lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;) { strings &lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;guard&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;first&lt;/span&gt; = strings.&lt;span style=&#34;color:#91d7e3&#34;&gt;first&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;else&lt;/span&gt; { &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        myLines.append(possibleLine: &lt;span style=&#34;color:#91d7e3&#34;&gt;first&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    .buttonBorderShape(.capsule)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This code just takes the first line in the pasteboard and tries to make a line out of it.&lt;/p&gt;
&lt;p&gt;This code works, but fails silently which can be hard to troubleshoot. I reworked this a bit later in the process to have &lt;code&gt;append(possibleLine: first)&lt;/code&gt; asynchronously return a success flag to let the view model pick some status text to display.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    PasteButton(payloadType: &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;.&lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;) { strings &lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        Task {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//statusText is an @State var&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            statusText = await myLines.updateOrWarn(input: strings.&lt;span style=&#34;color:#91d7e3&#34;&gt;first&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }.buttonBorderShape(.capsule)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;updateOrWarn&lt;/span&gt;(input:&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;?) async -&amp;gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; input &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;!=&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;nil&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;appendTask&lt;/span&gt; = await &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;.append(possibleLine:input!)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; appendTask ? &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Success&amp;#34;&lt;/span&gt; : &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Failed to add line text:&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;input!&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        } &lt;span style=&#34;color:#c6a0f6&#34;&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;No message waiting.&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;img src=&#34;phone_pastebutton.png&#34; alt=&#34;Screenshot of iOS simulator version this time, with the paste button&#34;&gt;&lt;/p&gt;
&lt;h2 id=&#34;summary&#34;&gt;Summary&lt;/h2&gt;
&lt;p&gt;That was it. That was all it took to be able to snag &amp;ldquo;Lines&amp;rdquo; from the web and shove them into our list. There&amp;rsquo;d be a long way to go to make this actually useful. Starting with seeing if the information can&amp;rsquo;t go from the extension to the shell app without the clipboard or if the clipboard path can be made less flakey.&lt;/p&gt;
</description>
    </item>
    
    
    
    <item>
      <title>But what&#39;s a plain Web Extension?</title>
      <link>https://whynotestflight.com/excuses/but-whats-a-plain-web-extension/</link>
      <pubDate>Fri, 02 Feb 2024 00:00:00 +0000</pubDate>
      
      <guid>https://whynotestflight.com/excuses/but-whats-a-plain-web-extension/</guid>
      <description>&lt;p&gt;Safari Web Extensions envelop a ball of HTML, javascript, CSS and JSON in an Xcodeproj and shove it into Safari.  That same ball can be shoved into Firefox and Chrome&amp;hellip; sort of. It has the same cross-browser issues that all other web development does and has always had.&lt;/p&gt;
&lt;p&gt;This post covers references on how to check an extension in Firefox and what&amp;rsquo;s in the manifest.json&lt;/p&gt;
&lt;h2 id=&#34;references&#34;&gt;References&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&#34;https://en.wikipedia.org/wiki/Browser_extension&#34;&gt;https://en.wikipedia.org/wiki/Browser_extension&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&#34;https://www.w3.org/community/webextensions/&#34;&gt;https://www.w3.org/community/webextensions/&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&#34;https://github.com/w3c/webextensions&#34;&gt;https://github.com/w3c/webextensions&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&#34;https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/What_are_WebExtensions&#34;&gt;https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/What_are_WebExtensions&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&#34;https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions&#34;&gt;https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&#34;https://extensionworkshop.com&#34;&gt;https://extensionworkshop.com&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&#34;https://developer.chrome.com/docs/extensions/reference/&#34;&gt;https://developer.chrome.com/docs/extensions/reference/&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;being-cross-compatible&#34;&gt;Being Cross Compatible&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://extensionworkshop.com/documentation/develop/browser-compatibility/&#34;&gt;https://extensionworkshop.com/documentation/develop/browser-compatibility/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/Build_a_cross_browser_extension&#34;&gt;https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/Build_a_cross_browser_extension&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;When reading about chrome extensions keep in mind that firefox and safari use &lt;code&gt;browser:&lt;/code&gt; among other difference&lt;/p&gt;
&lt;h2 id=&#34;checking-extension-in-firefox&#34;&gt;Checking Extension in Firefox&lt;/h2&gt;
&lt;p&gt;More info: &lt;a href=&#34;https://extensionworkshop.com/documentation/develop/getting-started-with-web-ext/&#34;&gt;https://extensionworkshop.com/documentation/develop/getting-started-with-web-ext/&lt;/a&gt;&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;brew install web-ext #or npm
web-ext --version
cd /PATH/TO/StandaloneExtension
web-ext run
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;See also about typing &amp;ldquo;&lt;a href=&#34;https://firefox-source-docs.mozilla.org/devtools-user/about_colon_debugging/index.html#Add-ons&#34;&gt;about:debugging&lt;/a&gt;&amp;rdquo; and &amp;ldquo;about:addons&amp;rdquo; into the FireFox toolbar.&lt;/p&gt;
&lt;h2 id=&#34;what-kinds-of-things-can-a-browser-extension-do&#34;&gt;What kinds of things can a Browser Extension do?&lt;/h2&gt;
&lt;p&gt;Finding out what a web extension does starts with reading its &lt;a href=&#34;https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json&#34;&gt;manifest.json&lt;/a&gt; Good news, a manifest.json can have &lt;code&gt;//&lt;/code&gt; comments!&lt;/p&gt;
&lt;p&gt;Here are some things you might find in a V3 one:&lt;/p&gt;
&lt;h3 id=&#34;extension-identity&#34;&gt;Extension Identity&lt;/h3&gt;
&lt;p&gt;Start with the basic meta information.  The minimum viable &lt;code&gt;manifest.json&lt;/code&gt; comprises of just. &lt;code&gt;manifest_version&lt;/code&gt;, &lt;code&gt;version&lt;/code&gt;, and &lt;code&gt;name&lt;/code&gt;.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-json&#34; data-lang=&#34;json&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;manifest_version&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;3&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;default_locale&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;en&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;name&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;__MSG_extension_name__&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;description&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;__MSG_extension_description__&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;version&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;1.0&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;homepage_url&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;https://example.com&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;If you see &lt;code&gt;__MSG_extension_name__&lt;/code&gt; look for a &lt;code&gt;default_locale&lt;/code&gt; and &lt;code&gt;_locales&lt;/code&gt; folder because that&amp;rsquo;s &lt;a href=&#34;https://en.wikipedia.org/wiki/Internationalization_and_localization&#34;&gt;internationalization and localization&lt;/a&gt; variable. More info on &lt;a href=&#34;https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/Internationalization&#34;&gt;i18n conventions&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Icon images can be a collection of pngs or a single svg.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-json&#34; data-lang=&#34;json&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;icons&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;:&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;&amp;#34;512&amp;#34;&lt;/span&gt;:&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;images/icon-512.svg&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }&lt;span style=&#34;color:#ed8796&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;icons&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;:&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;&amp;#34;48&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;images/icon-48.png&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;&amp;#34;96&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;images/icon-96.png&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;&amp;#34;512&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;images/icon-512.png&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;&amp;#34;1024&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;images/icon-1024.png&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }&lt;span style=&#34;color:#ed8796&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;background-processes&#34;&gt;Background Processes&lt;/h3&gt;
&lt;p&gt;&lt;a href=&#34;https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/background&#34;&gt;Background processes&lt;/a&gt; happen behind the scenes, but are not allowed to keep running indefinitely. Chrome and safari prefer the &lt;a href=&#34;https://developer.mozilla.org/en-US/docs/Web/API/Service_Worker_API&#34;&gt;service-worker API&lt;/a&gt; if available. Firefox falls back to the non-persistent background script.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-json&#34; data-lang=&#34;json&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;background&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;:&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;&amp;#34;service_worker&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;background.js&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;&amp;#34;scripts&amp;#34;&lt;/span&gt; : [&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;background.js&amp;#34;&lt;/span&gt;],
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;&amp;#34;persistent&amp;#34;&lt;/span&gt; : &lt;span style=&#34;color:#f5a97f&#34;&gt;false&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }&lt;span style=&#34;color:#ed8796&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Background processes frequently get paired with &lt;a href=&#34;https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/permissions#unlimited_storage&#34;&gt;storage&lt;/a&gt; or [unlimitedStorage][prm_ulm] &lt;a href=&#34;https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/permissions&#34;&gt;permission&lt;/a&gt;, which then take advantage of &lt;a href=&#34;https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/storage/local&#34;&gt;storage.local&lt;/a&gt;, &lt;a href=&#34;https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/storage/managed&#34;&gt;storage.managed&lt;/a&gt; or &lt;a href=&#34;https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/storage/session&#34;&gt;storage.session&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&#34;content-scripts&#34;&gt;Content Scripts&lt;/h3&gt;
&lt;p&gt;&lt;a href=&#34;https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/content_scripts&#34;&gt;Content scripts&lt;/a&gt; have a more constrained range of abilities than background scripts, but they run inside a loaded page&amp;rsquo;s DOM.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-json&#34; data-lang=&#34;json&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;content_scripts&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;:&lt;/span&gt; [{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;&amp;#34;js&amp;#34;&lt;/span&gt;: [ &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;content.js&amp;#34;&lt;/span&gt; ],
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;&amp;#34;matches&amp;#34;&lt;/span&gt;: [ &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;*://*.whynotestflight.com/*&amp;#34;&lt;/span&gt; ]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }]&lt;span style=&#34;color:#ed8796&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Several &lt;a href=&#34;https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/Match_patterns&#34;&gt;match patterns&lt;/a&gt; can be used to dial in what websites the script should try to load itself into, including &lt;code&gt;&amp;lt;all_urls&amp;gt;&lt;/code&gt;.&lt;/p&gt;
&lt;h3 id=&#34;tool-bar-actions&#34;&gt;Tool Bar Actions&lt;/h3&gt;
&lt;p&gt;Add an item to the browser tool bars with an &lt;a href=&#34;%5Bhttps://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/action%5D&#34;&gt;action&lt;/a&gt;&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-json&#34; data-lang=&#34;json&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;action&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;:&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;&amp;#34;default_popup&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;popup.html&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;&amp;#34;default_icon&amp;#34;&lt;/span&gt;: {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;&amp;#34;512&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;images/toolbar-icon-512.svg&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }&lt;span style=&#34;color:#ed8796&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;custom-browser-pages&#34;&gt;Custom Browser Pages&lt;/h3&gt;
&lt;p&gt;Replace new tab page or others. Comparable to &lt;a href=&#34;https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/chrome_url_overrides&#34;&gt;chrome_url_overrides&lt;/a&gt;&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-json&#34; data-lang=&#34;json&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;browser_url_overrides&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;:&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;&amp;#34;newtab&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;new_tab_page.html&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }&lt;span style=&#34;color:#ed8796&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;content-blockers&#34;&gt;Content Blockers&lt;/h3&gt;
&lt;p&gt;&lt;a href=&#34;https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/declarative_net_request&#34;&gt;declarative_net_request&lt;/a&gt; controls how network requests get handled and is the basis for content blockers.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-json&#34; data-lang=&#34;json&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;declarative_net_request&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;:&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;&amp;#34;rule_resources&amp;#34;&lt;/span&gt;: [
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#c6a0f6&#34;&gt;&amp;#34;id&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;MyRuleset&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#c6a0f6&#34;&gt;&amp;#34;enabled&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#f5a97f&#34;&gt;true&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#c6a0f6&#34;&gt;&amp;#34;path&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;rules.json&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        ]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }&lt;span style=&#34;color:#ed8796&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Example rules.json that blocks all images on all websites.  Rule sets can be static (life time of extension) or dynaimc (session conditional). &lt;a href=&#34;https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/declarativeNetRequest&#34;&gt;more&lt;/a&gt;&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-json&#34; data-lang=&#34;json&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;[
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;&amp;#34;id&amp;#34;&lt;/span&gt; : &lt;span style=&#34;color:#f5a97f&#34;&gt;1&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;&amp;#34;priority&amp;#34;&lt;/span&gt; : &lt;span style=&#34;color:#f5a97f&#34;&gt;1&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;&amp;#34;action&amp;#34;&lt;/span&gt; : { &lt;span style=&#34;color:#c6a0f6&#34;&gt;&amp;#34;type&amp;#34;&lt;/span&gt; : &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;block&amp;#34;&lt;/span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;&amp;#34;condition&amp;#34;&lt;/span&gt; :
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;&amp;#34;urlFilter&amp;#34;&lt;/span&gt; : &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;*.&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;&amp;#34;resourceTypes&amp;#34;&lt;/span&gt; : [ &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;image&amp;#34;&lt;/span&gt; ]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;controlling-abilities&#34;&gt;Controlling Abilities&lt;/h3&gt;
&lt;p&gt;An extension writer can request more or less abilities for their extension. Most browsers will then let the installer know how much more the extension wants to do.&lt;/p&gt;
&lt;h4 id=&#34;permissions&#34;&gt;Permissions&lt;/h4&gt;
&lt;p&gt;An extension can ask for install time permissions(&lt;a href=&#34;https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/permissions&#34;&gt;permissions&lt;/a&gt;) or runtime permissions(&lt;a href=&#34;https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/optional_permissions&#34;&gt;optional_permission&lt;/a&gt;, a subset). The desired permissions get listed in an array.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-json&#34; data-lang=&#34;json&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;permissions&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;:&lt;/span&gt; [ &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;activeTab&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;storage&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;scripting&amp;#34;&lt;/span&gt; ]&lt;span style=&#34;color:#ed8796&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Some common permissions:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&amp;ldquo;activeTab&amp;rdquo;: to inject scripts into the DOM, retrieve information like the URL for the active tab only.&lt;/li&gt;
&lt;li&gt;&amp;ldquo;scripting&amp;rdquo;: needed with activeTab to actually do the injecting.&lt;/li&gt;
&lt;li&gt;&amp;ldquo;storage&amp;rdquo;: use the storage apis (see &lt;a href=&#34;#background-processes&#34;&gt;background&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&amp;ldquo;tabs&amp;rdquo;: interact with &lt;em&gt;all&lt;/em&gt; the tabs and the tab system.&lt;/li&gt;
&lt;li&gt;&amp;ldquo;declarativeNetRequest&amp;rdquo;: to use &lt;a href=&#34;#content-blockers&#34;&gt;them&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&amp;ldquo;nativeMessaging&amp;rdquo;: to send messages to and from the extension&amp;rsquo;s &lt;a href=&#34;https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/Native_messaging&#34;&gt;delivery shell&lt;/a&gt;, the common use case is password managers.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;There are a handful of non-api permissions (like activeTab and [clipboardWrite]), but the bulk are about fine-grained dialing in of what parts of the &lt;a href=&#34;https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API&#34;&gt;web extensions API&lt;/a&gt; the extension actually needs.&lt;/p&gt;
&lt;h4 id=&#34;content-security-policy&#34;&gt;Content Security Policy&lt;/h4&gt;
&lt;p&gt;&lt;a href=&#34;https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/content_security_policy&#34;&gt;content_security_policy&lt;/a&gt; tightens or loosens what scripts from where can do. For example, the below would enable the use of &lt;a href=&#34;https://developer.mozilla.org/en-US/docs/WebAssembly&#34;&gt;web assembly&lt;/a&gt;.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-json&#34; data-lang=&#34;json&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;content_security_policy&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;:&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#c6a0f6&#34;&gt;&amp;#34;extension_pages&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;script-src &amp;#39;self&amp;#39; &amp;#39;wasm-unsafe-eval&amp;#39;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Manifest V3 gives a lot less latitude to extensions drawing in scripts the installer might not be able to reason about (remote, dynamic, etc) For example, it only allows &amp;rsquo;none&amp;rsquo;, &amp;lsquo;self&amp;rsquo;, and &amp;lsquo;wasm-unsafe-eval&amp;rsquo; as script source parameters. The default policy for V3:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;&amp;#34;script-src &amp;#39;self&amp;#39;; upgrade-insecure-requests;&amp;#34;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;In general terms:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Only local scripts and images.&lt;/li&gt;
&lt;li&gt;No eval, i.e. reading in strings on the fly as JavaScript.&lt;/li&gt;
&lt;li&gt;No JavaScript embedded in HTML tags.&lt;/li&gt;
&lt;li&gt;No WebAssembly unless explicitly asked for.&lt;/li&gt;
&lt;li&gt;http gets punted to https automatically.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;More details &lt;a href=&#34;https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/Content_Security_Policy#default_content_security_policy&#34;&gt;from Mozilla&lt;/a&gt; &lt;a href=&#34;https://w3c.github.io/webappsec-csp/&#34;&gt;from W3C&lt;/a&gt;&lt;/p&gt;
&lt;h4 id=&#34;externally-connectable&#34;&gt;Externally Connectable&lt;/h4&gt;
&lt;p&gt;&amp;ldquo;Externally connectable controls which other extensions and web pages can communicate with an extension using runtime.connect() and runtime.sendMessage() message passing. If externally_connectable is not specified, all extensions can communicate with each other but not with web pages.&amp;rdquo; &lt;a href=&#34;https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/externally_connectable&#34;&gt;page&lt;/a&gt;&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-json&#34; data-lang=&#34;json&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;externally_connectable&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;:&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;&amp;#34;matches&amp;#34;&lt;/span&gt;: [ &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;*://*.example.com/*&amp;#34;&lt;/span&gt; ]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }&lt;span style=&#34;color:#ed8796&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h4 id=&#34;load-resources&#34;&gt;Load Resources&lt;/h4&gt;
&lt;p&gt;&lt;a href=&#34;https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/web_accessible_resources&#34;&gt;web_accessible_resources&lt;/a&gt; determines what resources an extension can use depending on what page. Below example lets the script load files with &lt;code&gt;.xml&lt;/code&gt; and &lt;code&gt;.xsl&lt;/code&gt; extensions from a directory &amp;ldquo;xsl&amp;rdquo; in the extension&amp;rsquo;s root when the page in the activeTab has the &lt;code&gt;.xml&lt;/code&gt; extension.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-json&#34; data-lang=&#34;json&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;web_accessible_resources&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;:&lt;/span&gt; [
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;&amp;#34;resources&amp;#34;&lt;/span&gt; : [&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;xsl/*.xml&amp;#34;&lt;/span&gt;,&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;xsl/*.xsl&amp;#34;&lt;/span&gt;],
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;&amp;#34;matches&amp;#34;&lt;/span&gt;: [&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;*://*/*.xml&amp;#34;&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    ]
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;summary&#34;&gt;Summary&lt;/h2&gt;
&lt;p&gt;This catalogs a lot of the things that can be controlled, next post, how to use them.&lt;/p&gt;
</description>
    </item>
    
    
    
    <item>
      <title>Getting started with Safari Web Extensions</title>
      <link>https://whynotestflight.com/excuses/getting-started-with-safari-web-extensions/</link>
      <pubDate>Thu, 01 Feb 2024 00:00:00 +0000</pubDate>
      
      <guid>https://whynotestflight.com/excuses/getting-started-with-safari-web-extensions/</guid>
      <description>&lt;p&gt;This initial starting post will focus on getting started information with regards to Safari Web Extensions specifically. This post has:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Safari Web Extension Specific References&lt;/li&gt;
&lt;li&gt;Decision tree for how to get started&lt;/li&gt;
&lt;li&gt;Information on how to submodule out the Web Extension, if desired.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Safari Web Extensions really have 3 pieces, shown here from the 2020 WWDC talk &lt;a href=&#34;https://developer.apple.com/videos/play/wwdc2020/10665/&#34;&gt;Meet Safari Web Extensions&lt;/a&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A root/host app&lt;/li&gt;
&lt;li&gt;The app extension piece&lt;/li&gt;
&lt;li&gt;The actual web extension&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src=&#34;anatomy_swep.png&#34; alt=&#34;Triangular diagram of how the web extension, the native app extension and the native app itself all go together. &#34;&gt;&lt;/p&gt;
&lt;p&gt;It used to be that there was a whole Safari App Extension framework that was and still is macOS only. Since 2020 Apple pushes the Web Extensions (javascript) for as much as possible. Web Extensions work cross platform, and cross browser if done correctly.&lt;/p&gt;
&lt;p&gt;One doesn&amp;rsquo;t have to do any of the communication between the host app and the extension shown along the bottom of the image. The Web Extension can stand full on its own with the Xcodeproj as a delivery husk. If one already has a working Web Extension, this is the way. See &lt;a href=&#34;#option-2&#34;&gt;Option 2&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&#34;read--watch&#34;&gt;Read &amp;amp; Watch&lt;/h2&gt;
&lt;p&gt;It&amp;rsquo;s actually worth it to start with 2019 and watch through to 2023. The 2019 information shows the out of date-ish macOS only SFSafariApplication API, but it provides needed context for later changes.&lt;/p&gt;
&lt;p&gt;Umbrella Link: &lt;a href=&#34;https://developer.apple.com/documentation/safariservices/safari_web_extensions&#34;&gt;https://developer.apple.com/documentation/safariservices/safari_web_extensions&lt;/a&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;2019
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://developer.apple.com/videos/play/wwdc2019/720/&#34;&gt;What&amp;rsquo;s New in Safari Extensions&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;2020
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://developer.apple.com/videos/play/wwdc2020/10665/&#34;&gt;Meet Safari Web Extensions&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;code: &lt;a href=&#34;https://developer.apple.com/documentation/safariservices/safari_web_extensions/developing_a_safari_web_extension&#34;&gt;Developing a Safari Web Extension&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;code: &lt;a href=&#34;https://developer.apple.com/documentation/safariservices/safari_web_extensions/messaging_a_web_extension_s_native_app&#34;&gt;Messaging a Web Extension’s Native App&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;2021
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://developer.apple.com/videos/play/wwdc2021/10027/&#34;&gt;Explore Safari Web Extension improvements&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://developer.apple.com/videos/play/wwdc2021/10104/&#34;&gt;Meet Safari Web Extensions on iOS&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://developer.apple.com/videos/play/tech-talks/110148&#34;&gt;Build and deploy Safari Extensions for iOS&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;2022
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://developer.apple.com/videos/play/wwdc2022/10099&#34;&gt;What’s new in Safari Web Extensions&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://developer.apple.com/wwdc22/10100&#34;&gt;Create Safari Web Inspector Extensions&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;2023
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://developer.apple.com/videos/play/wwdc2023/10262/&#34;&gt;Rediscover Safari developer features&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://developer.apple.com/videos/play/wwdc2023/10119/&#34;&gt;What’s new in Safari extensions&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Helpful for Inter Process Communications:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://developer.apple.com/documentation/xcode/configuring-app-groups&#34;&gt;https://developer.apple.com/documentation/xcode/configuring-app-groups&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://developer.apple.com/documentation/foundation/xpc/&#34;&gt;https://developer.apple.com/documentation/foundation/xpc/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://developer.apple.com/documentation/updates/xpc/&#34;&gt;https://developer.apple.com/documentation/updates/xpc/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;ways-to-start&#34;&gt;Ways to start&lt;/h2&gt;
&lt;p&gt;Picking the one of the auto generated projects can help avoid the hard to troubleshoot &amp;ldquo;&lt;code&gt;The operation couldn’t be completed. (SFErrorDomain error 1.)&lt;/code&gt;&amp;rdquo; error when there is a mismatch between the native app and the extension information being passed to Safari. Which auto-generated option depends on what pieces exist already.&lt;/p&gt;
&lt;h3 id=&#34;option-1&#34;&gt;Option 1&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;No Extension&lt;/li&gt;
&lt;li&gt;No Existing App&lt;/li&gt;
&lt;li&gt;Care about the extension talking to the root app&lt;/li&gt;
&lt;li&gt;On both iOS and macOS.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;code&gt;Xcode &amp;gt; File &amp;gt; New Project &amp;gt; Multiplatform &amp;gt; Safari Extension App&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Will have a UIKit app with 4 targets. This is a good way to start even if you want to use SwiftUI because it sets up the four separate targets needed to use AppGroups successfully on BOTH iOS and macOS. AppGroups are one way to allow the Extension process to talk to the Root App process.&lt;/p&gt;
&lt;h3 id=&#34;option-2&#34;&gt;Option 2&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Have Extension&lt;/li&gt;
&lt;li&gt;No Existing App&lt;/li&gt;
&lt;li&gt;Care about the extension talking to the root app&lt;/li&gt;
&lt;li&gt;On both iOS and macOS&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Use the tool:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;xcrun safari-web-extension-converter $YOUR_EXTENSION_DIRECTORY_HERE&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;It will &lt;em&gt;copy&lt;/em&gt; the extension into a new UIKit App, giving feedback on what does and does not work for a Safari Web Extension.&lt;/p&gt;
&lt;h3 id=&#34;option-3&#34;&gt;Option 3&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;No or Yes on existing Extension&lt;/li&gt;
&lt;li&gt;Existing App&lt;/li&gt;
&lt;li&gt;Don&amp;rsquo;t care about the extension talking to the root app&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;From inside existing Xcodeproj, depending on what your app supports.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;Xcode &amp;gt; File &amp;gt; New Target &amp;gt; macOS &amp;gt; Safari Extension&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Xcode &amp;gt; File &amp;gt; New Target &amp;gt; iOS &amp;gt; Safari Extension&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Xcode &amp;gt; File &amp;gt; New Target &amp;gt; visionOS &amp;gt; Safari Extension&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;It is possible to just create the one new Target and add additional platform SDK support to it.&lt;/p&gt;
&lt;p&gt;If the web extension exists, replace the contents of the Resources folder with the those files. It may be useful to still run the web extension through the &lt;code&gt;xcrun&lt;/code&gt; tool first to see what errors pop us.&lt;/p&gt;
&lt;h3 id=&#34;option-4&#34;&gt;Option 4&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;No or Yes existing Extension&lt;/li&gt;
&lt;li&gt;Existing App&lt;/li&gt;
&lt;li&gt;Care about the extension talking to the root app&lt;/li&gt;
&lt;li&gt;On both iOS and macOS&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;From inside existing Xcodeproj, depending on what your app supports.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;Xcode &amp;gt; File &amp;gt; New Target &amp;gt; macOS &amp;gt; Safari Extension&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Xcode &amp;gt; File &amp;gt; New Target &amp;gt; iOS &amp;gt; Safari Extension&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Xcode &amp;gt; File &amp;gt; New Target &amp;gt; visionOS &amp;gt; Safari Extension&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Depending on what the communication strategy will be for inter-process communication it may be possible to create one Target and add platform support it. If planning on using AppGroups macOS and iOS(&amp;amp; visionOS?) &lt;em&gt;cannot share targets&lt;/em&gt; (leads to CFPrefsPlistSource/kCFPreferencesAnyUser problems), so at minimum do those separately.&lt;/p&gt;
&lt;p&gt;If the web extension exists, replace the contents of the Resources folder with the those files. It may be useful to still run the web extension through the &lt;code&gt;xcrun&lt;/code&gt; tool first to see what errors pop us.&lt;/p&gt;
&lt;h2 id=&#34;inter-process-communication-optional&#34;&gt;Inter-process Communication (Optional)&lt;/h2&gt;
&lt;p&gt;If the web extension does not need to integrate into an existing App infrastructure, don&amp;rsquo;t. It&amp;rsquo;s a PITA.&lt;/p&gt;
&lt;p&gt;But if you do want to, here are some options. Focusing on styles of inter-process communications that will work on both iOS and macOS.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;AppGroup between Root process and Extension process in native app
&lt;ul&gt;
&lt;li&gt;UserPrefs or shared files in the app group bundle.&lt;/li&gt;
&lt;li&gt;(&lt;a href=&#34;https://stackoverflow.com/questions/56134350/how-to-set-up-a-unix-domain-socket-in-ios&#34;&gt;fake unix domain sockets&lt;/a&gt;, type of shared file.)&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://developer.apple.com/documentation/xcode/configuring-app-groups/&#34;&gt;https://developer.apple.com/documentation/xcode/configuring-app-groups/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;XPCConnection between Root process and Extension process in native app
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://developer.apple.com/documentation/xpc/creating_xpc_services&#34;&gt;https://developer.apple.com/documentation/xpc/creating_xpc_services&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;An external server
&lt;ul&gt;
&lt;li&gt;go out onto the web.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;detaching-web-extension-development-from-app-development-optional&#34;&gt;Detaching Web Extension Development from App Development (Optional)&lt;/h2&gt;
&lt;h3 id=&#34;delete-if-have-an-extension-or-move-the-extensionfolderresources-folder-from-template&#34;&gt;Delete (if have an extension) or move the ExtensionFolder/Resources folder from template.&lt;/h3&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;cd PATH/TO/RootApp/ExtensionFolder
mv Resources ../../StandAloneExtension
cd ../../StandAloneExtension
git init . ; git add . ; git commit -m &amp;#34;Initialize repository&amp;#34;
&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=&#34;option-1-symlink&#34;&gt;Option 1: Symlink&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Pro:&lt;/strong&gt; don&amp;rsquo;t have to keep pushing and pulling between the local copies.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Con:&lt;/strong&gt; tricky if will be working on project with others since it will untraceable which version of the extension files the App thinks its pointing to. From &lt;a href=&#34;https://mirrors.edge.kernel.org/pub/software/scm/git/docs/git-config.html&#34;&gt;&lt;code&gt;man git-config&lt;/code&gt;&lt;/a&gt; -&lt;/li&gt;
&lt;/ul&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;core.symlinks:

If false, symbolic links are checked out as small plain files that contain the link text. ...Useful on filesystems like FAT that do not support symbolic links... The default is true...
&lt;/code&gt;&lt;/pre&gt;&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;cd PATH/TO/RootApp/
ln -s ../StandAloneExtension/ ExtensionFolder/Resources
&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=&#34;option-2-submodule&#34;&gt;Option 2: Submodule&lt;/h3&gt;
&lt;p&gt;Creating a submodule of a local folder makes it practical to go ahead and change files in Xcode, and then push the changes to their own branch of the local copy of the &amp;ldquo;real&amp;rdquo; repo for merging with the stand alone development work.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Pro:&lt;/strong&gt; What version you&amp;rsquo;re working on is always known and traceable by the App repo and any of its clones.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Con:&lt;/strong&gt; Have to remember to push the changes around. Pushing the main repo does not push the submodule.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;# Go to parent repo and add the submodule
cd PATH/TO/RootApp/
git -c protocol.file.allow=always submodule add ../StandAloneExtension/ ExtensionFolder/Resources
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;a href=&#34;https://git-scm.com/docs/git-config#Documentation/git-config.txt-protocolallow&#34;&gt;&lt;code&gt;-c protocol.file.allow=always&lt;/code&gt;&lt;/a&gt; because the file: schema is under lock down on macOS. Safer that way.&lt;/p&gt;
&lt;p&gt;in /PATH/TO/StandAloneExtension git repo create a new branch, but DO NOT CHECK IT OUT.
in the submodules directory, fetch that branch and check it out.&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;cd /PATH/TO/StandAloneExtension
git branch forXcproj ##StandAloneExtension should stay on main. 
## Optionally:
# git remote add xcpjSubmodule /PATH/TO/RootApp/ExtensionFolder/Resources
cd /PATH/TO/RootApp/ExtensionFolder/Resources
git status #see it&amp;#39;s its own little world.
git remote -v  #see our local folder is origin
git fetch
git checkout forXcproj
## if you already made changes in the submodule&amp;#39;s main
## rebasing forXcproj will pull those over.
git rebase main 
&lt;/code&gt;&lt;/pre&gt;&lt;h4 id=&#34;changes&#34;&gt;Changes&lt;/h4&gt;
&lt;h4 id=&#34;get-changes&#34;&gt;Get changes&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;git -c protocol.file.allow=always submodule update --remote ExtensionFolder/Resources&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;git -c protocol.file.allow=always submodule update --remote --merge&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;a href=&#34;https://git-scm.com/docs/git-config#Documentation/git-config.txt-protocolallow&#34;&gt;&lt;code&gt;-c protocol.file.allow=always&lt;/code&gt;&lt;/a&gt; because the file: schema is under lock down on macOS. Safer that way.&lt;/p&gt;
&lt;h4 id=&#34;send-changes&#34;&gt;Send Changes&lt;/h4&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;cd /PATH/TO/RootApp/ExtensionFolder/Resources
# git add &amp;amp; commit, etc
git push 
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Make sure that the origin local repo does not have the branch you&amp;rsquo;re trying to push to checked out or you will get an error like:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt; ! [remote rejected] main -&amp;gt; main (branch is currently checked out)
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This is why we have created a branch just for the Xcode project. This is also why adding the Xcodproj as a remote for &lt;code&gt;../StandAloneExtension&lt;/code&gt; might be a good idea, it enables pulling from there.&lt;/p&gt;
&lt;h2 id=&#34;summary&#34;&gt;Summary&lt;/h2&gt;
&lt;p&gt;All of this before a lick of Swift or Javascript. Worth it.&lt;/p&gt;
</description>
    </item>
    
    
    
    <item>
      <title>What if instead of a CLI, Plugins? Part 4, Prebuild plugins &amp; misc</title>
      <link>https://whynotestflight.com/excuses/what-if-instead-of-a-cli-plugins-part-4-prebuild-plugins-misc/</link>
      <pubDate>Mon, 29 Jan 2024 00:00:00 +0000</pubDate>
      
      <guid>https://whynotestflight.com/excuses/what-if-instead-of-a-cli-plugins-part-4-prebuild-plugins-misc/</guid>
      <description>&lt;h3 id=&#34;related-repo&#34;&gt;Related Repo&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/carlynorama/PluginExplorer&#34; title=&#34;PluginExplorer repo, main branch&#34;&gt;PluginExplorer&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;All the plugins run their tools inside a sandbox. A command plugin&amp;rsquo;s tools can be given permission to leave &lt;a href=&#34;https://whynotestflight.com/excuses/what-if-instead-of-a-cli-plugins-part-1-command-plugins/#update-packageswift&#34;&gt;via the Package manifest&lt;/a&gt;. Build plugins (in-build and prebuild) plugin tools cannot.  Not without removing the whole sandbox.  (5.9, 01/2024).&lt;/p&gt;
&lt;p&gt;The sandbox makes it easier to bring a new plugin into the system because whether the fear is poorly written code or nefarious code&amp;hellip; well it&amp;rsquo;s in a sandbox.&lt;/p&gt;
&lt;p&gt;I bring this up because I couldn&amp;rsquo;t come up with a single solitary interesting idea of something to do for a prebuild plugin that wouldn&amp;rsquo;t have been better off as a command plugin (needed permissions to write to the source folder) or in-build plugin (expensive work).  So I decided to try leaving the sandbox.&lt;/p&gt;
&lt;p&gt;The &lt;a href=&#34;https://developer.apple.com/videos/play/wwdc2022/110401&#34;&gt;Create Swift Package Plugins&lt;/a&gt;( min 19) video shows generating localization resources. Now that, as Boris Buegling said, is generally useful. I recommend that example.&lt;/p&gt;
&lt;p&gt;It takes advantage of the fact that prebuild plugins don&amp;rsquo;t need any input information other than the arguments for the tool and only ask for an output directory. The lack of specificity on inputs and outputs means the plugin&amp;rsquo;s executable tool will run every build. The Package Manger has no list to check against to make sure everything expected of it has already been handled, so the tool gets run to be sure.&lt;/p&gt;
&lt;p&gt;My example comes in two parts:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Leaving the confines of the package to find resources elsewhere on the computer and then brining them into the build directory as a zip archive. (No sandbox violation)&lt;/li&gt;
&lt;li&gt;Bundling up all the source files and saving them into a &amp;ldquo;Storage&amp;rdquo; folder inside the package. (Sandbox violation)&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;set-up&#34;&gt;Set Up&lt;/h2&gt;
&lt;p&gt;Making a prebuild plugin will be pretty straight forward. Similar enough to a build plugin, it just takes a little editing.&lt;/p&gt;
&lt;p&gt;It still gets added to Package.swift the same way&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//Plugin and target in same package example &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        .executableTarget(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            name:&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;plugin-tester&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            dependencies: [
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                .product(name: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;ArgumentParser&amp;#34;&lt;/span&gt;, package: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;swift-argument-parser&amp;#34;&lt;/span&gt;),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            ],
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            path:&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Sources/PluginTesterCLI&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            exclude: [&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Data&amp;#34;&lt;/span&gt;],
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            plugins: [&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;MyInBuildPlugin&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;MyPreBuildPlugin&amp;#34;&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        ),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        .plugin(name: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;MyPreBuildPlugin&amp;#34;&lt;/span&gt;, capability: .buildTool()),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And it still lives in the Plugins folder.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-txt&#34; data-lang=&#34;txt&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;└── MyFancyPackage
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    └── Plugins
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    │   └── MyPreBuildPlugin
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    │       └──plugin.swift
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    └── Package.swift
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    └── .git
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    └── .gitignore
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;pluginswift&#34;&gt;plugin.swift&lt;/h2&gt;
&lt;p&gt;Let&amp;rsquo;s look at my ill advised prebuild command that I&amp;rsquo;ve wrapped in a function returning a &lt;code&gt;PackagePlugin.Command&lt;/code&gt;.  (below)&lt;/p&gt;
&lt;p&gt;&lt;code&gt;zsh&lt;/code&gt; (a shell program) plays the roll of the executable. The tool can be any executable the SPM can see, so I went for it to see if I could just shove the shell in there.&lt;/p&gt;
&lt;p&gt;My very long shell command zips up the requested directory (&lt;code&gt;folderToZip&lt;/code&gt;) with a timestamped archive name and then pares down the stored archives to only the 5 most recent. &lt;code&gt;folderToZip&lt;/code&gt; can be a path to anywhere local, although I did not do extensive testing.  Prebuild commands don&amp;rsquo;t track inputs and the sandbox doesn&amp;rsquo;t reign them in.  The outputDir does get limited by the sandbox.  It expects to be within the plugin&amp;rsquo;s working directory in the build folder.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;zipFileCommand&lt;/span&gt;(outputDir:Path, folderToZip:Path) -&amp;gt; PackagePlugin.Command {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;parentDirectory&lt;/span&gt; = folderToZip.removingLastComponent().string
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;folderOnly&lt;/span&gt; = folderToZip.lastComponent
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;zipNCleanCommand&lt;/span&gt; = &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;cd &lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;parentDirectory&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt; &amp;amp;&amp;amp; zip -r &lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;outputDir&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;/snapshot_$(date +&amp;#39;%Y-%m-%dT%H-%M-%S&amp;#39;).zip &lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;folderOnly&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt; &amp;amp;&amp;amp; cd - &amp;amp;&amp;amp; cd &lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;outputDir&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt; &amp;amp;&amp;amp; ls -1t | tail -n +6 | xargs rm -f&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; .prebuildCommand(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            displayName: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;------------ MyPreBuildPlugin ------------&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            executable: .&lt;span style=&#34;color:#ed8796&#34;&gt;init&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;/bin/zsh&amp;#34;&lt;/span&gt;), &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//also Path(&amp;#34;/bin/zsh&amp;#34;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            arguments: [&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;-c&amp;#34;&lt;/span&gt;, zipNCleanCommand],
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//environment: [:], in case it&amp;#39;s needed... &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            outputFilesDirectory: outputDir)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The function can slot in to a plugin that plays nicely with &lt;code&gt;swift run&lt;/code&gt; and Xcode.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;@main
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;MyPreBuildPlugin&lt;/span&gt;:BuildToolPlugin {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;createBuildCommands&lt;/span&gt;(context: PackagePlugin.PluginContext, target: PackagePlugin.Target) async &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; -&amp;gt; [PackagePlugin.Command] {   
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;outputDir&lt;/span&gt; = context.pluginWorkDirectory
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;folderToZip&lt;/span&gt; = Path(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;/Users/{your path here}/TestZipFolder&amp;#34;&lt;/span&gt;) 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;from MPBP:&amp;#34;&lt;/span&gt;, outputDir)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; [ zipFileCommand(outputDir: outputDir, folderToZip: folderToZip)]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#if&lt;/span&gt; &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;canImport&lt;/span&gt;(&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;XcodeProjectPlugin&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;XcodeProjectPlugin&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;extension&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;MyPreBuildPlugin&lt;/span&gt;: XcodeBuildToolPlugin {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// Entry point for creating build commands for targets in Xcode projects.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;createBuildCommands&lt;/span&gt;(context: XcodePluginContext, target: XcodeTarget) &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; -&amp;gt; [Command] {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;outputDir&lt;/span&gt; = context.pluginWorkDirectory
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;folderToZip&lt;/span&gt; = context.xcodeProject.directory.appending([target.displayName])
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;       &lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;from MPBP:&amp;#34;&lt;/span&gt;, outputDir)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;       &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; [ zipFileCommand(outputDir: outputDir, folderToZip: folderToZip)]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#endif&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The report generated from running the plugin attached to a package from within Xcode looks like: (from report Inspector, shown in &lt;a href=&#34;https://whynotestflight.com/excuses/what-if-instead-of-a-cli-plugins-part-2-start-a-build-plugin/#switching-to-xcode&#34;&gt;previous post&lt;/a&gt;)&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;/usr/bin/sandbox-exec -p &amp;#34;(version 1)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(deny default)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(import \&amp;#34;system.sb\&amp;#34;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(allow file-read*)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(allow process*)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(allow mach-lookup (global-name \&amp;#34;com.apple.lsd.mapdb\&amp;#34;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(allow file-write*
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    (subpath \&amp;#34;/private/tmp\&amp;#34;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    (subpath \&amp;#34;/private/var/folders/px/cd_t0mkd6gq0ntb0v6kqj__00000gn/T\&amp;#34;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(deny file-write*
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    (subpath \&amp;#34;/Users/{...}/Developer/GitHub/PluginExplorer\&amp;#34;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(allow file-write*
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    (subpath \&amp;#34;/Users/{...}/DerivedData/PluginExplorer-dikuycmkyjcfkhffudvbwxrkjxih/SourcePackages/plugins/pluginexplorer.output/plugin-tester/MyPreBuildPlugin\&amp;#34;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;#34; /bin/zsh -c &amp;#34;cd /Users/{...}/Developer/GitHub &amp;amp;&amp;amp; zip -r /Users/{...}/Library/Developer/Xcode/DerivedData/PluginExplorer-dikuycmkyjcfkhffudvbwxrkjxih/SourcePackages/plugins/pluginexplorer.output/plugin-tester/MyPreBuildPlugin/snapshot_$(date +&amp;#39;%Y-%m-%dT%H-%M-%S&amp;#39;).zip TestZipFolder &amp;amp;&amp;amp; cd - &amp;amp;&amp;amp; cd /Users/{...}/Library/Developer/Xcode/DerivedData/PluginExplorer-dikuycmkyjcfkhffudvbwxrkjxih/SourcePackages/plugins/pluginexplorer.output/plugin-tester/MyPreBuildPlugin &amp;amp;&amp;amp; ls -1t | tail -n +6 | xargs rm -f&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  adding: TestZipFolder/ (stored 0%)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  adding: TestZipFolder/robot_stylized_bc.png (deflated 3%)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  adding: TestZipFolder/robot_realistic_m.png (deflated 0%)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  adding: TestZipFolder/robot_stylized_m.png (deflated 24%)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  adding: TestZipFolder/robot_papercraft_r.png (deflated 0%)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;There are clearly defined allowed and not allowed places to save files.&lt;/p&gt;
&lt;p&gt;Now lets try scenario 2, writing an archive of the current source files to a storage folder.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// could also try some  Path(&amp;#34;/Users/{---}/&amp;#34;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;outputDir&lt;/span&gt; = context.package.directory.appending([&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Storage&amp;#34;&lt;/span&gt;])
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;inputDir&lt;/span&gt; = target.directory
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Make sure /$TARGET_PACKAGE/Storage actually exists and added to .gitignore to be safe. Run the Scheme again. This build should fail. At the bottom of the MyPreBuildPlugin report will be:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;zip I/O error: Operation not permitted
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;zip error: Could not create output file
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Open Terminal and&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## plugin-tester is the name of the executable target the &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## prebuild plugin is attached to. &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#91d7e3&#34;&gt;cd&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;$TARGET_PACKAGE&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;swift run  plugin-tester &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## get same message&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;swift run --disable-sandbox plugin-tester &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## smooth sailing&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ls Storage &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## archive should be listed&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Xcode 15.2 cannot run packages outside of safe mode. I have read about build plugins being run outside of safe mode when &lt;a href=&#34;https://github.com/apple/swift-package-manager/issues/7121&#34;&gt;linked to an actual xcproj&lt;/a&gt;. I gave a cursory attempt, but could not make that work. I am just not very familiar with customizing builds for Xcode projects. Again a topic for another day.&lt;/p&gt;
&lt;h2 id=&#34;other-options&#34;&gt;Other options&lt;/h2&gt;
&lt;p&gt;I got to wondering if there could be another way to approach this without busting out of the sandbox. In general the sandbox makes sure one doesn&amp;rsquo;t do dumb things, and turning it off for all of the code when it just needs to be off for a small part of it seems unwise.&lt;/p&gt;
&lt;p&gt;Command plugins have way more flexibility with their permissions. With the &lt;a href=&#34;https://forums.swift.org/t/swift-run-from-inside-a-command-plugin-bad-idea-or-terrible-idea/69678/&#34;&gt;help from the swift forums&lt;/a&gt; I have the start of a command plugin that could be used in the future anytime I&amp;rsquo;m tempted to write a build plugin that needs to be run out of the sandbox because it manages its own build.&lt;/p&gt;
&lt;p&gt;It uses a &lt;a href=&#34;https://github.com/apple/swift-package-manager/blob/main/Sources/PackagePlugin/PackageManagerProxy.swift&#34;&gt;proxy for the PackageManager&lt;/a&gt;, and it seems to be a &lt;a href=&#34;https://github.com/swift-server/swift-aws-lambda-runtime/blob/8d9f44b7838750b103ad2ad49055e8333d719e8a/Plugins/AWSLambdaPackager/Plugin.swift#L151&#34;&gt;widely&lt;/a&gt; &lt;a href=&#34;https://github.com/search?q=%22packageManager.build%22+language%3ASwift&amp;amp;type=code&#34;&gt;adopted&lt;/a&gt; approach.&lt;/p&gt;
&lt;p&gt;It only works for packages and even in package mode does seem to have trouble in Xcode 15.2 (the only IDE I&amp;rsquo;ve tried.) The implementation of the proxy in that Xcode does not seem to be complete? It throws a &lt;code&gt;unspecified(&amp;quot;internalError(\&amp;quot;unimplemented\&amp;quot;)&amp;quot;)&lt;/code&gt; error. That&amp;rsquo;s a draw back but I&amp;rsquo;m hoping it will be resolved in the coming months since this seems to be a more officially supported path?&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ve dumped the code that would be in plugin.swift at the bottom of the post. It offers two options. After doing the permission-needing the work the plugin can:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Build every thing, including dependencies, then run the named target&lt;/li&gt;
&lt;li&gt;Build only the named target then run it.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;summary&#34;&gt;Summary&lt;/h2&gt;
&lt;p&gt;Not a lot to add just on prebuild plugins because they aren&amp;rsquo;t that different than build plugins. It was fun to try playing around with throwing different commands I had in my bin folder into the executable parameter. I even wrote a command plugin that could cd to another folder and do a &lt;code&gt;swift run&lt;/code&gt;.  With the sandbox off it actually worked, but super &lt;a href=&#34;https://forums.swift.org/t/swift-run-from-inside-a-command-plugin-bad-idea-or-terrible-idea/69678/&#34;&gt;ill advised&lt;/a&gt;.  Was glad to learn about that crazy meta way in to packageManger. That&amp;rsquo;s amazing.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//  CustomBuildNRun.swift&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//  Created by Carlyn Maw on 1/29/24.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//  &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//Use style ONE  or TWO, not both like the below.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;PackagePlugin&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;Foundation&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;@main
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;CustomBuildNRun&lt;/span&gt;: CommandPlugin {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// Entry point for command plugins applied to Swift Packages.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;performCommand&lt;/span&gt;(context: PackagePlugin.PluginContext, arguments: [&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;]) async &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//DO WORK&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;targetToRunName&lt;/span&gt; = &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;DemoFruitStore&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;arguments&lt;/span&gt; = [&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;fruit_list&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;citrus&amp;#34;&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;parameters&lt;/span&gt; = PackageManager.BuildParameters()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//parameters.logging = printCommands ? .verbose : .concise&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//parameters.configuration = release ? .release : .debug&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//print(parameters)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//------------------------------------  STYLE ONE&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//rebuilds EVERYBODY, result has all the artifacts from every&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//plugin, etc.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;result&lt;/span&gt; = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; packageManager.build(.all(includingTests: &lt;span style=&#34;color:#f5a97f&#34;&gt;false&lt;/span&gt;), parameters: parameters)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(result.logText)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;-----------&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(result.builtArtifacts)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; result.succeeded {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;resultToRun&lt;/span&gt; = result.builtArtifacts.&lt;span style=&#34;color:#91d7e3&#34;&gt;first&lt;/span&gt;(&lt;span style=&#34;color:#c6a0f6&#34;&gt;where&lt;/span&gt;: {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#f4dbd6&#34;&gt;$0&lt;/span&gt;.kind == .executable &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;$0&lt;/span&gt;.path.lastComponent == targetToRunName
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            }) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;message&lt;/span&gt; = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; runProcess(URL(fileURLWithPath: resultToRun.path.string), arguments: arguments)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(message)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//------------------------------------  END STYLE ONE&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//------------------------------------  STYLE TWO&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//the .build() function can also filter on product.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//Does not rebuild plugins, etc.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;targets&lt;/span&gt; = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; context.package.targets(named: [targetToRunName])
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;       &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;targetsToRun&lt;/span&gt; = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; targets.flatMap {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;           &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; extractRunnableTargets(&lt;span style=&#34;color:#f4dbd6&#34;&gt;$0&lt;/span&gt;, parameters: parameters)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;       &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; targetsToRun.forEach { targetToRun &lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;message&lt;/span&gt; = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; runProcess(URL(fileURLWithPath: targetToRun.path.string), arguments: arguments)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(message)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//------------------------------------  END STYLE TWO&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;extractRunnableTargets&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; target:Target, parameters:PackageManager.BuildParameters) &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; -&amp;gt; [PackageManager.BuildResult.BuiltArtifact] {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;trying for target... &lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;target.name&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;result&lt;/span&gt; = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; packageManager.build(.target(target.name), parameters: parameters)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(result.logText)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; result.succeeded  {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;           &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; result.builtArtifacts.&lt;span style=&#34;color:#91d7e3&#34;&gt;filter&lt;/span&gt;({&lt;span style=&#34;color:#f4dbd6&#34;&gt;$0&lt;/span&gt;.kind == .executable })
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        } &lt;span style=&#34;color:#c6a0f6&#34;&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; []
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;@discardableResult
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;runProcess&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; tool:URL, arguments:[&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;] = [], workingDirectory:URL? = &lt;span style=&#34;color:#f5a97f&#34;&gt;nil&lt;/span&gt;) &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; -&amp;gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;task&lt;/span&gt; = &lt;span style=&#34;color:#91d7e3&#34;&gt;Process&lt;/span&gt;()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;pipe&lt;/span&gt; = Pipe()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    task.standardOutput = pipe
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    task.standardError = pipe
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    task.arguments = arguments
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;workingDirectory&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        task.currentDirectoryURL = workingDirectory
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//task.qualityOfService&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//task.environment&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    task.standardInput = &lt;span style=&#34;color:#f5a97f&#34;&gt;nil&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    task.executableURL = tool
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; task.run()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;data&lt;/span&gt; = pipe.fileHandleForReading.readDataToEndOfFile()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;output&lt;/span&gt; = &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;(data: data, encoding: .utf8)&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;!&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    task.waitUntilExit()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; task.terminationStatus == &lt;span style=&#34;color:#f5a97f&#34;&gt;0&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;||&lt;/span&gt; task.terminationStatus == &lt;span style=&#34;color:#f5a97f&#34;&gt;2&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; output
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    } &lt;span style=&#34;color:#c6a0f6&#34;&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(output)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#c6a0f6&#34;&gt;throw&lt;/span&gt; CustomProcessError.unknownError(exitCode: task.terminationStatus)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;enum&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;CustomProcessError&lt;/span&gt;: Error {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#c6a0f6&#34;&gt;case&lt;/span&gt; unknownError(exitCode: &lt;span style=&#34;color:#91d7e3&#34;&gt;Int32&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description>
    </item>
    
    
    
    <item>
      <title>What if instead of a CLI, Plugins? Part 3, The Actual Code Gen</title>
      <link>https://whynotestflight.com/excuses/what-if-instead-of-a-cli-plugins-part-3-the-actual-code-gen/</link>
      <pubDate>Thu, 25 Jan 2024 00:00:00 +0000</pubDate>
      
      <guid>https://whynotestflight.com/excuses/what-if-instead-of-a-cli-plugins-part-3-the-actual-code-gen/</guid>
      <description>&lt;h3 id=&#34;related-repos&#34;&gt;Related Repos&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/carlynorama/BuildPluginExample/&#34; title=&#34;repo for the plugin&#34;&gt;BuildPluginExample&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/carlynorama/BuildPluginExampleTarget/&#34; title=&#34;repo for the cli that imports the plugin&#34;&gt;BuildPluginExampleTarget&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/carlynorama/PluginExplorer&#34; title=&#34;PluginExplorer repo, main branch&#34;&gt;PluginExplorer&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Allll right. In &lt;a href=&#34;https://whynotestflight.com/excuses/what-if-instead-of-a-cli-plugins-part-2-start-a-build-plugin/&#34;&gt;the last post&lt;/a&gt; I created the very basic outline of a minimal viable in-build plugin.  I&amp;rsquo;m going to start from that base code (The pt-1 tag &lt;a href=&#34;https://github.com/carlynorama/BuildPluginExample/tags&#34; title=&#34;repo for the plugin, pt3 branch&#34;&gt;Plugin&lt;/a&gt;,&lt;a href=&#34;https://github.com/carlynorama/BuildPluginExampleTarget/tags&#34; title=&#34;repo for the cli that imports the plugin, pt3 branch&#34;&gt;CLI&lt;/a&gt;), adding the code gen for $DEMOPACKAGE and then loop back and make sure it works in the MacOS/iOS sample app as well. I did not make a repo for the sample App, it&amp;rsquo;s really is just the &amp;ldquo;New Project&amp;rdquo; App, I swear.&lt;/p&gt;
&lt;p&gt;But before I start I want to explain why I&amp;rsquo;ll be doing most of the $DEMOPACKAGE work in Xcode instead of the command line/VScode the way I&amp;rsquo;d normally do package oriented work.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;PROBLEM 1&lt;/strong&gt;: Since &lt;code&gt;swift run&lt;/code&gt; uses &lt;a href=&#34;https://manpages.org/env/1&#34; title=&#34;man page for env&#34;&gt;process environment variables&lt;/a&gt; to help determine if it should run the build plugin tools again, any changes to the process environment triggers a fresh run. Some of those environment variables will be &lt;a href=&#34;https://github.com/apple/swift-package-manager/blob/0416a2805df975018bda111606fab1f736e8e2db/Sources/Basics/EnvironmentVariables.swift#L67&#34;&gt;ignored in the future&lt;/a&gt;, but not yet. For example &lt;code&gt;TERM_SESSION_ID&lt;/code&gt; changes with new shells and that causes a lot of headaches with both VSCode and my multi-Terminal window workflow. The build plugin just CONSTANTLY rebuilds. This one &lt;a href=&#34;https://forums.swift.org/t/rebuild-times-in-new-shell-significantly-slower/68054/&#34; title=&#34;thread on swift forums about slow rebuild times&#34;&gt;has&lt;/a&gt; &lt;a href=&#34;https://github.com/apple/swift-package-manager/pull/7056&#34; title=&#34;filter transient env variables from manifest and plugin cache keys&#34;&gt;fixes&lt;/a&gt; &lt;a href=&#34;https://github.com/swift-server/vscode-swift/issues/625&#34; title=&#34;Rebuild times consistently take quite long in Build Task&#34;&gt;already&lt;/a&gt; &lt;a href=&#34;https://forums.swift.org/t/rebuild-times-in-new-shell-significantly-slower/68054&#34;&gt;down the&lt;/a&gt; &lt;a href=&#34;https://github.com/apple/swift-package-manager/issues/6676&#34; title=&#34;Linker failures when using plugin in dependencies of target&#34;&gt;pipe&lt;/a&gt; in &lt;a href=&#34;https://github.com/apple/swift-package-manager/blob/0416a2805df975018bda111606fab1f736e8e2db/Sources/Basics/EnvironmentVariables.swift#L67&#34;&gt;5.10&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;PROBLEM 2&lt;/strong&gt;: The VSCode extension doesn&amp;rsquo;t detect the &lt;a href=&#34;https://forums.swift.org/t/vscode-doesnt-seem-to-find-generated-code/64278&#34; title=&#34;thread on swift forums about missing VSCode link&#34;&gt;generated code&lt;/a&gt;&amp;rsquo;s symbols so when you write code by hand which depends on that generated code a &lt;code&gt;[&amp;quot;cannot find $MYNEWTHING in scope&amp;quot; sourcekitd ]&lt;/code&gt; error pops up. The code can compile and run just fine, but all the red squiggly line errors grate on my eyeballs.  This problem &lt;a href=&#34;https://github.com/apple/sourcekit-lsp/issues/620&#34; title=&#34;Jump to definition requires a reload after build&#34;&gt;resides&lt;/a&gt; on &lt;a href=&#34;https://github.com/apple/sourcekit-lsp/issues/676&#34; title=&#34;SourceKit-LSP appears to interfere with SwiftPM build plugins&#34;&gt;upstream&lt;/a&gt; &lt;a href=&#34;https://github.com/apple/sourcekit-lsp/issues/665&#34; title=&#34;Source generated by build plugin is ignored&#34;&gt;projects&lt;/a&gt; (&lt;a href=&#34;https://github.com/apple/swift-package-manager/&#34; title=&#34;SPM repo, main&#34;&gt;SPM&lt;/a&gt; and &lt;a href=&#34;https://github.com/apple/sourcekit-lsp/&#34; title=&#34;SourceKit-LSP repo, main&#34;&gt;SourceKit-lsp&lt;/a&gt;) &lt;a href=&#34;https://github.com/apple/swift-package-manager/issues/6700&#34; title=&#34;Add ability to get compiler arguments for files generated by build plugin without running build plugin&#34;&gt;not the&lt;/a&gt; extension, it appears.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;PROBLEM 3&lt;/strong&gt;: Well, this was more of a me problem. Some of my linker errors came from listing the build plugin in the executable target&amp;rsquo;s &lt;code&gt;dependencies&lt;/code&gt; parameter instead of the &lt;strong&gt;&lt;code&gt;plugins&lt;/code&gt;&lt;/strong&gt; parameter in the &lt;code&gt;Package.swift&lt;/code&gt; definition. The lack of a warning has been fixed &lt;a href=&#34;https://github.com/apple/swift-package-manager/issues/6676&#34; title=&#34;Linker failures when using plugin in dependencies of target&#34;&gt;in 5.10&lt;/a&gt;. I show the fixed &lt;code&gt;Package.swift entry&lt;/code&gt; below.&lt;/p&gt;
&lt;p&gt;Meanwhile over in Xcode it all just works. Both for packages and projects.  Installing one of the forks of 5.10 could have been another option, but that will be for another day.&lt;/p&gt;
&lt;h2 id=&#34;add-the-data-files-to-demopackage&#34;&gt;Add The Data Files to $DEMOPACKAGE&lt;/h2&gt;
&lt;p&gt;Start with just two files in an excluded directory.&lt;/p&gt;
&lt;p&gt;In the $DEMOPACKAGE root directory (aka BuildPluginExampleTarget) (aka DemoFruitStore):&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;mkdir Sources/Data
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;mv Sources/apple.txt Sources/Data/apple.txt
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;touch Sources/Data/citrus.txt
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;update-the-packageswift-if-havent-already&#34;&gt;Update the Package.swift, if haven&amp;rsquo;t already&lt;/h3&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;         .executableTarget(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            name: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;DemoFruitStore&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            dependencies: [
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                .product(name: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;ArgumentParser&amp;#34;&lt;/span&gt;, 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                      package: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;swift-argument-parser&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//NOT HERE !!! .product(name: , package: &amp;#34;FruitStoreBuild&amp;#34;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            ],
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            exclude: [&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Data&amp;#34;&lt;/span&gt;], &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//&amp;lt;&amp;lt;=== what the exclusion should look like&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            plugins: [
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                 &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//HERE!!&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                .plugin(name: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;MyPluginName&amp;#34;&lt;/span&gt;, package: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;MyPluginName&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            ]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        ),
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;update-the-contents-of-the-text-files&#34;&gt;Update the contents of the text files.&lt;/h3&gt;
&lt;h4 id=&#34;appletxt&#34;&gt;apple.txt&lt;/h4&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;//apple.swift
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;let apple = &amp;#34;macintosh&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h4 id=&#34;citrustxt&#34;&gt;citrus.txt&lt;/h4&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;//citrus.swift
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;let citrus = &amp;#34;calamondin&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;update-mybuildplugin-to-point-to-data-directory&#34;&gt;Update MyBuildPlugin to point to Data Directory&lt;/h2&gt;
&lt;p&gt;in $BUILDPLUGINDIR/Plugins/$MYBUILDPLUGIN/plugin.swift&lt;/p&gt;
&lt;p id=&#34;packageGetFiles&#34;&gt;Change the &lt;code&gt;createBuildCommands&lt;/code&gt; that&amp;rsquo;s part of the &lt;code&gt;BuildToolPlugin&lt;/code&gt; conformance to only look in the &amp;ldquo;Data&amp;rdquo; folder using the &lt;a href=&#34;https://whynotestflight.com/excuses/what-if-instead-of-a-cli-plugins-part-2-start-a-build-plugin/#look-a-little-deeper&#34;&gt;function from last post&lt;/a&gt;&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//OLD: filesFromDirectory(path: target.directory, &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//                        shallow: false)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//The updated location. One known folder, no recursion. &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;dataDirectory&lt;/span&gt; = target.directory.appending([&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Data&amp;#34;&lt;/span&gt;])
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;filesToProcess&lt;/span&gt; = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; filesFromDirectory(path: dataDirectory)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now the plugin won&amp;rsquo;t work for any text file outside of the hard coded folder. A plugin designed for sharing or a broader use-case might make a different choice, but this works for this case.&lt;/p&gt;
&lt;h2 id=&#34;update-custom-tool&#34;&gt;Update Custom Tool&lt;/h2&gt;
&lt;p&gt;In $BUILDPLUGINDIR/Sources/MyBuildPluginTool/main.swift we now need to get the contents of the text file being inspected and shove it into the swift file.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;Foundation&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;arguments&lt;/span&gt; = ProcessInfo().arguments
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; arguments.&lt;span style=&#34;color:#91d7e3&#34;&gt;count&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;lt;&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;4&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;missing arguments&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; (input, output) = (arguments[&lt;span style=&#34;color:#f5a97f&#34;&gt;1&lt;/span&gt;], arguments[&lt;span style=&#34;color:#f5a97f&#34;&gt;3&lt;/span&gt;])
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;outputURL&lt;/span&gt; = URL(fileURLWithPath: output)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//------------ NEW LINE IS HERE ----------------&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;contentsOfInputFile&lt;/span&gt; = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;(contentsOf: URL(fileURLWithPath: input))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; contentsOfInputFile.write(to: outputURL, atomically: &lt;span style=&#34;color:#f5a97f&#34;&gt;true&lt;/span&gt;, encoding: .utf8)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;update-demopackage-and-run&#34;&gt;Update $DEMOPACKAGE and RUN!&lt;/h2&gt;
&lt;p&gt;Update $DEMOPACKAGEDIR/Sources/$DEMOPACKAGE.swift (or $DEMOPACKAGEDIR/Sources/$DEMOPACKAGE/main.swift depending on your current file structure)&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;ArgumentParser&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;@main
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;DemoFruitStore&lt;/span&gt;: ParsableCommand {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;configuration&lt;/span&gt; = CommandConfiguration(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        abstract: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;For Testing The Plugins&amp;#34;&lt;/span&gt;, 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        version: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;0.0.0&amp;#34;&lt;/span&gt;, 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        subcommands: [hello.&lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;], 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        defaultSubcommand: hello.&lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;hello&lt;/span&gt;: ParsableCommand {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;mutating&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;run&lt;/span&gt;() &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Hello, &lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;apple&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;!&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Hello, &lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;citrus&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;!&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The IDE will likely complain that these values do not exits. They should in a minute, so ignore the warning.&lt;/p&gt;
&lt;p&gt;If using the command line&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## not NEEEDED can be useful to try if getting errors&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;swift package clean 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## Make the new code, no point in running without it&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## Will have linker errors&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;swift build 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## will build again&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;swift run 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## will build for debugging without tools firing off&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;swift run
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This should result in something like:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;### START HERE&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;DemoFruitStore % swift build
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Building &lt;span style=&#34;color:#c6a0f6&#34;&gt;for&lt;/span&gt; debugging...
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;[&lt;/span&gt;3/3&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;]&lt;/span&gt; Linking my-code-generator
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Build complete! &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;(&lt;/span&gt;3.05s&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Building &lt;span style=&#34;color:#c6a0f6&#34;&gt;for&lt;/span&gt; debugging...
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;FIIIIIIIIIIIIIINNNNNNNNNDDDMMMEEEEEEEEEEEEEEEEE
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;from MyBuildPluginTool: &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;{&lt;/span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;$PATH_TO_REPO&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;}&lt;/span&gt;/DemoFruitStore/Sources/Data/citrus.txt
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;from MyBuildPluginTool: &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;{&lt;/span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;$PATH_TO_REPO&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;}&lt;/span&gt;/DemoFruitStore/.build/plugins/outputs/demofruitstore/DemoFruitStore/FruitStoreBuild/citrus.swift
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;FIIIIIIIIIIIIIINNNNNNNNNDDDMMMEEEEEEEEEEEEEEEEE
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;from MyBuildPluginTool: &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;{&lt;/span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;$PATH_TO_REPO&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;}&lt;/span&gt;/DemoFruitStore/Sources/Data/apple.txt
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;from MyBuildPluginTool: &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;{&lt;/span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;$PATH_TO_REPO&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;}&lt;/span&gt;/DemoFruitStore/.build/plugins/outputs/demofruitstore/DemoFruitStore/FruitStoreBuild/apple.swift
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ld: Undefined symbols:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  DemoFruitStore.apple.unsafeMutableAddressor : Swift.String, referenced from:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      DemoFruitStore.DemoFruitStore.hello.run&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;()&lt;/span&gt; throws -&amp;gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;()&lt;/span&gt; in DemoFruitStore.swift.o
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  DemoFruitStore.citrus.unsafeMutableAddressor : Swift.String, referenced from:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      DemoFruitStore.DemoFruitStore.hello.run&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;()&lt;/span&gt; throws -&amp;gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;()&lt;/span&gt; in DemoFruitStore.swift.o
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;clang: error: linker &lt;span style=&#34;color:#91d7e3&#34;&gt;command&lt;/span&gt; failed with &lt;span style=&#34;color:#91d7e3&#34;&gt;exit&lt;/span&gt; code &lt;span style=&#34;color:#f5a97f&#34;&gt;1&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;(&lt;/span&gt;use -v to see invocation&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;[&lt;/span&gt;55/56&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;]&lt;/span&gt; Linking DemoFruitStore
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;###-------------------- FIRST RUN --------------------&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;DemoFruitStore % swift run
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Building &lt;span style=&#34;color:#c6a0f6&#34;&gt;for&lt;/span&gt; debugging...
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Build complete! &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;(&lt;/span&gt;0.18s&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Building &lt;span style=&#34;color:#c6a0f6&#34;&gt;for&lt;/span&gt; debugging...
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;FIIIIIIIIIIIIIINNNNNNNNNDDDMMMEEEEEEEEEEEEEEEEE
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;from MyBuildPluginTool: &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;{&lt;/span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;$PATH_TO_REPO&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;}&lt;/span&gt;/DemoFruitStore/Sources/Data/apple.txt
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;from MyBuildPluginTool: &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;{&lt;/span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;$PATH_TO_REPO&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;}&lt;/span&gt;/DemoFruitStore/.build/plugins/outputs/demofruitstore/DemoFruitStore/FruitStoreBuild/apple.swift
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;FIIIIIIIIIIIIIINNNNNNNNNDDDMMMEEEEEEEEEEEEEEEEE
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;from MyBuildPluginTool: &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;{&lt;/span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;$PATH_TO_REPO&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;}&lt;/span&gt;/DemoFruitStore/Sources/Data/citrus.txt
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;from MyBuildPluginTool: &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;{&lt;/span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;$PATH_TO_REPO&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;}&lt;/span&gt;/DemoFruitStore/.build/plugins/outputs/demofruitstore/DemoFruitStore/FruitStoreBuild/citrus.swift
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;[&lt;/span&gt;8/8&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;]&lt;/span&gt; Linking DemoFruitStore
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Build complete! &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;(&lt;/span&gt;0.69s&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Hello, macintosh!
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Hello, calamondin!
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;###-------------------- SECOND RUN --------------------&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;DemoFruitStore % swift run
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Building &lt;span style=&#34;color:#c6a0f6&#34;&gt;for&lt;/span&gt; debugging...
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Build complete! &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;(&lt;/span&gt;0.12s&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Hello, macintosh!
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Hello, calamondin!
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;w00t! Success! Opening up a new Terminal window or other method of changing the shell environment will trigger the build to run the tools again.&lt;/p&gt;
&lt;p&gt;For a silly build plugin trick&amp;hellip;&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#91d7e3&#34;&gt;export&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;HELLO&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#39;Hello World&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# echo $HELLO #to believe it took, or `env`&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;swift run
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&amp;hellip;will trigger a fresh build with tool run.&lt;/p&gt;
&lt;h2 id=&#34;switching-to-xcode&#34;&gt;Switching to Xcode&lt;/h2&gt;
&lt;p&gt;Xcode now sees the generated symbols fine and Vscode does not. As a result, the rest I did in Xcode. I will still write the command line commands for documentation purposes, but in Xcode I was actually using &lt;a href=&#34;https://developer.apple.com/documentation/xcode/customizing-the-build-schemes-for-a-project/&#34;&gt;&lt;code&gt;Schema&lt;/code&gt;&lt;/a&gt;s.  Xcode provides the ability to run Schema to any package or project with an executable in it. Even if that executable is a CLI. Different than typical CLI interactions, when the Schema runs (CMD + R or the &amp;ldquo;play button&amp;rdquo;, just like any project) none of the build messages get printed to the &lt;code&gt;Console&lt;/code&gt;. It&amp;rsquo;s all in the Report Inspector. When working with Xcode fiddly-clickers get the reward. Click and right click everywhere. Even blank white space. Secret Buttons Everywhere. (some marked in image)&lt;/p&gt;
&lt;table&gt;
  &lt;thead&gt;
      &lt;tr&gt;
          &lt;th&gt;section of build report showing print outs from the plugin itself&lt;/th&gt;
          &lt;th&gt;section of build report showing print outs from the called tool&lt;/th&gt;
      &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;img src=&#34;build_report_plugin_print.png&#34; alt=&#34;Screenshot of Xcode window, Navigator with the current build selected and Console with the output of the successful run also can be seen in addition to the report described in the caption.&#34;&gt;&lt;/td&gt;
          &lt;td&gt;&lt;img src=&#34;build_report_tool_print_annotated2.png&#34; alt=&#34;Screenshot of Xcode window, identical to its pair except the content of the report.&#34;&gt;&lt;/td&gt;
      &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Schema are XML files with build actions described within. Below is the description of the command I&amp;rsquo;m about to build.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-xml&#34; data-lang=&#34;xml&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#c6a0f6&#34;&gt;&amp;lt;CommandLineArguments&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;         &lt;span style=&#34;color:#c6a0f6&#34;&gt;&amp;lt;CommandLineArgument&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#8aadf4&#34;&gt;argument =&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;fruit_list&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#8aadf4&#34;&gt;isEnabled =&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;YES&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;         &lt;span style=&#34;color:#c6a0f6&#34;&gt;&amp;lt;/CommandLineArgument&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;         &lt;span style=&#34;color:#c6a0f6&#34;&gt;&amp;lt;CommandLineArgument&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#8aadf4&#34;&gt;argument =&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;citrus&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#8aadf4&#34;&gt;isEnabled =&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;YES&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;         &lt;span style=&#34;color:#c6a0f6&#34;&gt;&amp;lt;/CommandLineArgument&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#c6a0f6&#34;&gt;&amp;lt;/CommandLineArguments&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;To get to the below window to edit a Scheme via the GUI (recommended) choose &lt;code&gt;Product &amp;gt; Scheme &amp;gt; Edit Scheme&lt;/code&gt; from the drop down menus to edit the currently selected Scheme.  The Arguments page is shown, but on the Options page all the way at the bottom one can switch the Console to be Terminal and Xcode will launch a window instead.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;schema_edit.png&#34; alt=&#34;Screenshot of editing a schema for a CLI that takes arguments&#34;&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://developer.apple.com/documentation/xcode/customizing-the-build-schemes-for-a-project/&#34;&gt;https://developer.apple.com/documentation/xcode/customizing-the-build-schemes-for-a-project/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://developer.apple.com/documentation/xcode/creating-a-standalone-swift-package-with-xcode#Build-your-targets-and-run-unit-tests&#34;&gt;https://developer.apple.com/documentation/xcode/creating-a-standalone-swift-package-with-xcode#Build-your-targets-and-run-unit-tests&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Those get shared in the .git repo. The .gitignore generated by &lt;code&gt;the swift package init&lt;/code&gt; command works really well for including these helpful files while not sharing private info. (&lt;code&gt;.swiftpm/xcode/xcshareddata/xcschemes&lt;/code&gt; is shared while other items in &lt;code&gt;.swiftpm&lt;/code&gt; are not)&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/carlynorama/BuildPluginExampleTarget/tree/main/.swiftpm/xcode/xcshareddata/xcschemes&#34;&gt;schemes in GitHub project&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;fruit_list.xcscheme&#34;&gt;local version of fruit_list.xcscheme&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Referenced &lt;code&gt;.gitignore&lt;/code&gt; for posterity:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-git&#34; data-lang=&#34;git&#34;&gt;.DS_Store
/.build
/Packages
xcuserdata/
DerivedData/
.swiftpm/configuration/registries.json
.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata
.netrc
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&#34;adding-the-fruit-store&#34;&gt;Adding the Fruit Store&lt;/h2&gt;
&lt;p&gt;Create a new file called $DEMOPACKAGE/Sources/FruitStoreCommand.swift&lt;/p&gt;
&lt;p&gt;This file will hold the &lt;code&gt;fruit_list&lt;/code&gt; command. It will let us test what fruits we actually have gotten through from the data.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//  FruitStoreCommand.swift&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//  Created by Carlyn Maw on 1/24/24.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;ArgumentParser&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;protocol&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;Fruit&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;name&lt;/span&gt;:&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt; {&lt;span style=&#34;color:#c6a0f6&#34;&gt;get&lt;/span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;FruitStore&lt;/span&gt;:&lt;span style=&#34;color:#91d7e3&#34;&gt;Dictionary&lt;/span&gt;&amp;lt;&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;,[any Fruit]&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;gt;&lt;/span&gt; = [:]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;extension&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;DemoFruitStore&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;fruit_list&lt;/span&gt;: ParsableCommand {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        @Argument &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;fruitType&lt;/span&gt;:&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;?
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;mutating&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;run&lt;/span&gt;() &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;fruitType&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt;  &lt;span style=&#34;color:#f4dbd6&#34;&gt;fruitList&lt;/span&gt; = FruitStore[fruitType] {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    &lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;We have &lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;fruitList.&lt;span style=&#34;color:#91d7e3&#34;&gt;count&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;fruitType&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;(s).&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    fruitList.forEach({&lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;- &lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;$0&lt;/span&gt;.name&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;)})
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                } &lt;span style=&#34;color:#c6a0f6&#34;&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                 &lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;No fruit of type &lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;fruitType&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt; in the FruitStore.&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            } &lt;span style=&#34;color:#c6a0f6&#34;&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;full fruit store&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;FruitStore&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;update-the-caller-config--run&#34;&gt;Update the Caller Config &amp;amp; Run&lt;/h3&gt;
&lt;p&gt;Update the config in $DEMOPACKAGEDIR/Sources/$DEMOPACKAGE.swift to recognize the new command&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;configuration&lt;/span&gt; = CommandConfiguration(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        abstract: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;For Testing The Plugins&amp;#34;&lt;/span&gt;, 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        version: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;0.0.0&amp;#34;&lt;/span&gt;, 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        subcommands: [hello.&lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;, fruit_list.&lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;],  &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//CHANGED&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        defaultSubcommand: hello.&lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;) 
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;run-the-executable&#34;&gt;Run the Executable&lt;/h3&gt;
&lt;p&gt;Set up two Schemas,&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;one with just &lt;code&gt;fruit_list&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;one with &lt;code&gt;fruit_list&lt;/code&gt; and &lt;code&gt;citrus&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;CMD + R and the Console should show the following outputs respectively. I put what the CLI input would have been as a convenience. Its not actually in the Console. &lt;code&gt;Program ended with exit code: 0&lt;/code&gt;, the successful no-errors 0 code announcement, does get printed. I may remove it in future pastes but if anyone reading this had never seen it before. Its okay. &lt;a href=&#34;https://en.wikipedia.org/wiki/Exit_status&#34;&gt;It means all good&lt;/a&gt;. Heres &lt;a href=&#34;https://tldp.org/LDP/abs/html/exitcodes.html&#34;&gt;some numbers that would be less good&lt;/a&gt;&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## DemoFruitStore % swift run DemoFruitStore fruit_list&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;full fruit store
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;[&lt;/span&gt;:&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Program ended with &lt;span style=&#34;color:#91d7e3&#34;&gt;exit&lt;/span&gt; code: &lt;span style=&#34;color:#f5a97f&#34;&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## DemoFruitStore % swift run DemoFruitStore fruit_list citrus&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;No fruit of &lt;span style=&#34;color:#91d7e3&#34;&gt;type&lt;/span&gt; citrus in the FruitStore.
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Program ended with &lt;span style=&#34;color:#91d7e3&#34;&gt;exit&lt;/span&gt; code: &lt;span style=&#34;color:#f5a97f&#34;&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;add-fruitstore-loading-code&#34;&gt;Add FruitStore loading code.&lt;/h2&gt;
&lt;p&gt;Let&amp;rsquo;s put items in the &lt;code&gt;FruitStore&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Update &lt;code&gt;citrus.txt&lt;/code&gt; with a struct and an attempt to load an instance into FruitStore&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;//citrus.swift
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;let citrus = &amp;#34;calamondin&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;struct Citrus:Fruit {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    let name:String
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;FruitStore[&amp;#34;citrus&amp;#34;] = [ Citrus(name:&amp;#34;\(citrus)&amp;#34;)]
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Run the code and magic happens. Xcode OPENS the auto generated file and flags the &lt;code&gt;expressions are not allowed at the top level&lt;/code&gt; error. Nice. Very cool. The actual file lives deep in the build folder. It&amp;rsquo;s possible to get there by selecting &lt;code&gt;Product &amp;gt; Show Build Folder in Finder&lt;/code&gt; from the menu, navigating up one level then back down to the file (&lt;code&gt;/PluginTesterApp-APPHASH/SourcePackages/plugins/PluginTesterApp.output/PluginTesterApp/MyBuildPlugin&lt;/code&gt;)&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;expression_top_level.png&#34; alt=&#34;Screenshot of Xcode being a clever girl and opening the file as described above.&#34;&gt;&lt;/p&gt;
&lt;p&gt;But in the mean time the error needs fixing. Replace the direct assignment with&amp;hellip;&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;func addCitrus() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    FruitStore[&amp;#34;citrus&amp;#34;] = [ Citrus(name:&amp;#34;\(citrus)&amp;#34;)]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&amp;hellip;and add &lt;code&gt;addCitrus()&lt;/code&gt; to the &lt;code&gt;fruit_lists&lt;/code&gt; run code. I briefly tried adding a convenience &lt;code&gt;init&lt;/code&gt; but that screwed up &lt;code&gt;ParsableCommand&lt;/code&gt; conformance more than I wanted to wrestle with today. For now this will be fine since we don&amp;rsquo;t have many fruits yet.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;fruit_list&lt;/span&gt;: ParsableCommand {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        @Argument &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;fruitType&lt;/span&gt;:&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;?
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;mutating&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;run&lt;/span&gt;() &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//cannot find add addCitrus in scope warning. &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//Ignore it. Code will still build and it will go away.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            addCitrus()   
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## DemoFruitStore % swift run DemoFruitStore fruit_list&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;full fruit store
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;[&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;citrus&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;[&lt;/span&gt;DemoFruitStore.Citrus&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;(&lt;/span&gt;name: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;calamondin&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;)]]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Program ended with &lt;span style=&#34;color:#91d7e3&#34;&gt;exit&lt;/span&gt; code: &lt;span style=&#34;color:#f5a97f&#34;&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## DemoFruitStore % swift run DemoFruitStore fruit_list citrus&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;We have &lt;span style=&#34;color:#f5a97f&#34;&gt;1&lt;/span&gt; citrus&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;(&lt;/span&gt;s&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;)&lt;/span&gt;.
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;- calamondin
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Program ended with &lt;span style=&#34;color:#91d7e3&#34;&gt;exit&lt;/span&gt; code: &lt;span style=&#34;color:#f5a97f&#34;&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;We can do the same for &lt;code&gt;apple.txt&lt;/code&gt;. Add the &lt;code&gt;addApple()&lt;/code&gt; under the &lt;code&gt;addCitrus()&lt;/code&gt; in &lt;code&gt;fruit_list.run()&lt;/code&gt; and it works, too.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;% swift run DemoFruitStore fruit_list
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;full fruit store
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## line split mine&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;[&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;apple&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;[&lt;/span&gt;DemoFruitStore.Apple&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;(&lt;/span&gt;name: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;macintosh&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;)]&lt;/span&gt;, &lt;span style=&#34;color:#8aadf4&#34;&gt;\ &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;citrus&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;[&lt;/span&gt;DemoFruitStore.Citrus&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;(&lt;/span&gt;name: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;calamondin&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;)]]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Program ended with &lt;span style=&#34;color:#91d7e3&#34;&gt;exit&lt;/span&gt; code: &lt;span style=&#34;color:#f5a97f&#34;&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;That step proved that the build system would find the code in the build folder if it was there without having the code be available in the source folder. It also proved that if we could get code that looked like that into the file it would work. Let&amp;rsquo;s generate it from data, not write it by hand now.&lt;/p&gt;
&lt;h2 id=&#34;actual-code-gen-in-mainswift&#34;&gt;Actual Code Gen in main.swift&lt;/h2&gt;
&lt;p&gt;Change &lt;code&gt;citrus.txt&lt;/code&gt; and &lt;code&gt;apple.txt&lt;/code&gt; to just have the single words &lt;code&gt;calamondin&lt;/code&gt; and &lt;code&gt;macintosh&lt;/code&gt; in them respectively. No quotes. Nothing but a single word each.&lt;/p&gt;
&lt;p&gt;in &lt;code&gt;$BUILDPLUGINDIR/Sources/MyBuildPluginTool/main.swift&lt;/code&gt; we need to get a little fancier than before. The below Swift code will recreate what I wrote by hand in the text file a minute ago.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;Foundation&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;arguments&lt;/span&gt; = ProcessInfo().arguments
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; arguments.&lt;span style=&#34;color:#91d7e3&#34;&gt;count&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;lt;&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;4&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;missing arguments&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; (input, output) = (arguments[&lt;span style=&#34;color:#f5a97f&#34;&gt;1&lt;/span&gt;], arguments[&lt;span style=&#34;color:#f5a97f&#34;&gt;3&lt;/span&gt;])
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;outputURL&lt;/span&gt; = URL(fileURLWithPath: output)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;inputURL&lt;/span&gt; = URL(fileURLWithPath: input)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;generatedCode&lt;/span&gt; = generateHeader()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;fileBase&lt;/span&gt; = inputURL.deletingPathExtension().lastPathComponent
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;structName&lt;/span&gt; = fileBase.capitalized
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;generatedCode.append(generateStruct(structName: structName))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;contentsOfInputFile&lt;/span&gt; = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;(contentsOf: URL(fileURLWithPath: input))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                                .trimmingCharacters(&lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt;: .whitespacesAndNewlines)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;generatedCode.append(generateAddToFruitStore(base:fileBase, 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                                             structName:structName, 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                                             itemToAdd: contentsOfInputFile))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; generatedCode.write(to: outputURL, atomically: &lt;span style=&#34;color:#f5a97f&#34;&gt;true&lt;/span&gt;, encoding: .utf8)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;generateHeader&lt;/span&gt;() -&amp;gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&amp;#34;&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;        import Foundation
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;        &amp;#34;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;generateStruct&lt;/span&gt;(structName:some StringProtocol) -&amp;gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&amp;#34;&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;    &lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\n&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;    struct &lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;structName&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;:Fruit {
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;        let name:String
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;    &amp;#34;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;generateAddToFruitStore&lt;/span&gt;(base:some StringProtocol, 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                       structName:some StringProtocol, 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                        itemToAdd:some StringProtocol) -&amp;gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&amp;#34;&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;    let &lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;base&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt; = &amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;\&lt;/span&gt;(itemToAdd)&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;    func add&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;base.capitalized&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;        FruitStore[&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;\&lt;/span&gt;(base)&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;] = [ &lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;structName&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;(name:&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;\\&lt;/span&gt;(&lt;span style=&#34;color:#ed8796&#34;&gt;\&lt;/span&gt;(base))&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;)]
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;    &amp;#34;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And it works! (The simple-code-gen tag &lt;a href=&#34;https://github.com/carlynorama/BuildPluginExample/tags&#34; title=&#34;repo for the plugin, pt3 branch&#34;&gt;Plugin&lt;/a&gt;, &lt;a href=&#34;https://github.com/carlynorama/BuildPluginExampleTarget/tags&#34; title=&#34;repo for the cli that imports the plugin, pt3 branch&#34;&gt;CLI&lt;/a&gt;)&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;full fruit store
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## line split mine&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;[&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;citrus&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;[&lt;/span&gt;DemoFruitStore.Citrus&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;(&lt;/span&gt;name: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;calamondin&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;)]&lt;/span&gt;, &lt;span style=&#34;color:#8aadf4&#34;&gt;\ &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;apple&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;[&lt;/span&gt;DemoFruitStore.Apple&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;(&lt;/span&gt;name: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;macintosh&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;)]]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Program ended with &lt;span style=&#34;color:#91d7e3&#34;&gt;exit&lt;/span&gt; code: &lt;span style=&#34;color:#f5a97f&#34;&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;But what if we wanted more items in the text files?&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;itemsFromFile&lt;/span&gt; = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;(contentsOf: URL(fileURLWithPath: input))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                                                        .&lt;span style=&#34;color:#91d7e3&#34;&gt;split&lt;/span&gt;(separator: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\n&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;generatedCode.append(generateAddToFruitStore(base:fileBase, 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                                       structName:structName, 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                                       itemsToAdd:itemsFromFile))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;generateAddToFruitStore&lt;/span&gt;(base:some StringProtocol, 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                       structName:some StringProtocol, 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                       itemsToAdd:[some StringProtocol]) -&amp;gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;initStrings&lt;/span&gt; = itemsToAdd.&lt;span style=&#34;color:#91d7e3&#34;&gt;map&lt;/span&gt; { &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;structName&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;(name:&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;$0&lt;/span&gt;.capitalized&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;)&amp;#34;&lt;/span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;fruitArrayCode&lt;/span&gt; = &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;[&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;initStrings.joined&lt;span style=&#34;color:#a6da95&#34;&gt;(&lt;/span&gt;separator: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;,&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;))&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;]&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;insertCode&lt;/span&gt; = &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&amp;#34;&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;        FruitStore[&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;\&lt;/span&gt;(base)&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;] = &lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;fruitArrayCode&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;    &amp;#34;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&amp;#34;&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;    //note: only changes PER RE-BUILD with the plugin.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;    let &lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;base&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt; = &amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;\&lt;/span&gt;(itemsToAdd.randomElement() ?? &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;No items in list&amp;#34;&lt;/span&gt;)&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;    func add&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;base.capitalized&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;         &lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;insertCode&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;    &amp;#34;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And now that works, too!&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## line splits mine.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;full fruit store
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;[&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;apple&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;[&lt;/span&gt;DemoFruitStore.Apple&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;(&lt;/span&gt;name: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Macintosh&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;)&lt;/span&gt;, &lt;span style=&#34;color:#8aadf4&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;&lt;/span&gt;    DemoFruitStore.Apple&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;(&lt;/span&gt;name: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Rome&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;)&lt;/span&gt;,  &lt;span style=&#34;color:#8aadf4&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;&lt;/span&gt;    DemoFruitStore.Apple&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;(&lt;/span&gt;name: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Fuji&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;)&lt;/span&gt;,  &lt;span style=&#34;color:#8aadf4&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;&lt;/span&gt;    DemoFruitStore.Apple&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;(&lt;/span&gt;name: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Cortland&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;)]&lt;/span&gt;, &lt;span style=&#34;color:#8aadf4&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;citrus&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;[&lt;/span&gt;DemoFruitStore.Citrus&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;(&lt;/span&gt;name: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Calamondin&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;)&lt;/span&gt;, &lt;span style=&#34;color:#8aadf4&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;&lt;/span&gt;    DemoFruitStore.Citrus&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;(&lt;/span&gt;name: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Orange&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;)&lt;/span&gt;,  &lt;span style=&#34;color:#8aadf4&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;&lt;/span&gt;    DemoFruitStore.Citrus&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;(&lt;/span&gt;name: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Yuzu&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;)&lt;/span&gt;,  &lt;span style=&#34;color:#8aadf4&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;&lt;/span&gt;    DemoFruitStore.Citrus&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;(&lt;/span&gt;name: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Limequat&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;)]]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Program ended with &lt;span style=&#34;color:#91d7e3&#34;&gt;exit&lt;/span&gt; code: &lt;span style=&#34;color:#f5a97f&#34;&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Note the &lt;code&gt;let \(base) = &amp;quot;\(itemsToAdd.randomElement() ?? &amp;quot;No items in list&amp;quot;)&amp;quot;&lt;/code&gt; line. This will only generate when the tool rebuilds that Swift file. That means if you change &lt;code&gt;citrus.txt&lt;/code&gt; the citrus fruit greeted by &lt;code&gt;hello&lt;/code&gt; will likely change, but the apple will not change.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## run hello&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Hello, fuji!
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Hello, yuzu!
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Program ended with &lt;span style=&#34;color:#91d7e3&#34;&gt;exit&lt;/span&gt; code: &lt;span style=&#34;color:#f5a97f&#34;&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## make a change to citrus.txt&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Hello, fuji!
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Hello, orange!
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Program ended with &lt;span style=&#34;color:#91d7e3&#34;&gt;exit&lt;/span&gt; code: &lt;span style=&#34;color:#f5a97f&#34;&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;back-in-the-app&#34;&gt;Back in the App&lt;/h2&gt;
&lt;p&gt;Open back up the sample app project and do the following:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Drag the &amp;ldquo;Data&amp;rdquo; folder from the &lt;code&gt;DemoProject&lt;/code&gt; over to the App target. Make sure the &amp;ldquo;copy&amp;rdquo; check box is checked.&lt;/li&gt;
&lt;li&gt;The &lt;a href=&#34;https://whynotestflight.com/excuses/what-if-instead-of-a-cli-plugins-part-1-command-plugins/&#34;&gt;command plugin&lt;/a&gt; shows the enclosing FOLDER listed as the resource. Not the files inside. Select the folder in the project navigator and then use the file inspector to remove it from the target by unselecting the tick box.&lt;/li&gt;
&lt;li&gt;Add the needed code to the ContentView&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;SwiftUI&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;protocol&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;Fruit&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;name&lt;/span&gt;:&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt; {&lt;span style=&#34;color:#c6a0f6&#34;&gt;get&lt;/span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;FruitStore&lt;/span&gt;:&lt;span style=&#34;color:#91d7e3&#34;&gt;Dictionary&lt;/span&gt;&amp;lt;&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;,[any Fruit]&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;gt;&lt;/span&gt; = [:]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;ContentView&lt;/span&gt;: View {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//Even better would be at the init of the App. &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;init&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        addCitrus()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        addApple()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;body&lt;/span&gt;: some View {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        VStack {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            Image(systemName: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;globe&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                .imageScale(.large)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                .foregroundStyle(.tint)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//Displaying them all a an exercise for the reader.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            Text(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Hello, &lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;FruitStore[&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;apple&amp;#34;&lt;/span&gt;]?[&lt;span style=&#34;color:#f5a97f&#34;&gt;0&lt;/span&gt;].name ?? &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;nothing here&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        .padding()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;img src=&#34;DataFolderSetup.png&#34; alt=&#34;Screenshot Xcode window with the project navigator with the Data folder selected, the file inspector open to the Data folders info, and the content area showing ContentView.swift&#34;&gt;&lt;/p&gt;
&lt;p&gt;Back in the plugin the &lt;code&gt;XcodePluginContext&lt;/code&gt; needs an update to point to the &amp;ldquo;Data&amp;rdquo; folder like the package&amp;rsquo;s code.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;createBuildCommands&lt;/span&gt;(context: XcodePluginContext, target: XcodeTarget) &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; -&amp;gt; [Command] {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;generatorTool&lt;/span&gt; = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; context.tool(named: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;my-code-generator&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//New directory fetch&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;dataDirectory&lt;/span&gt; = context.xcodeProject.directory.appending([target.displayName, &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Data&amp;#34;&lt;/span&gt;])
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;filesToProcess&lt;/span&gt; = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; filesFromDirectory(path:dataDirectory)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//Also different. It&amp;#39;s already and array of Paths.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; filesToProcess.compactMap {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            createBuildCommand(&lt;span style=&#34;color:#c6a0f6&#34;&gt;for&lt;/span&gt;: &lt;span style=&#34;color:#f4dbd6&#34;&gt;$0&lt;/span&gt;, &lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt;: context.pluginWorkDirectory, with: generatorTool.path)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;I&amp;rsquo;m using my &lt;a href=&#34;https://whynotestflight.com/excuses/what-if-instead-of-a-cli-plugins-part-2-start-a-build-plugin/#look-a-little-deeper&#34;&gt;function that loads files&lt;/a&gt; from the end of the last post, same as the &lt;a href=&#34;#packageGetFiles&#34;&gt;&lt;code&gt;BuildToolPlugin&lt;/code&gt;&amp;rsquo; conforming function&lt;/a&gt;  .  What&amp;rsquo;s important, and fragile, is the &lt;code&gt;Path&lt;/code&gt;. The &lt;code&gt;context.xcodeProject.directory.appending([target.displayName, &amp;quot;Data&amp;quot;])&lt;/code&gt; relies on the &lt;code&gt;displayName&lt;/code&gt; of the Target. I have less than 100% confidence that the displayName will always be the directory name. In a project context we are not given the &lt;code&gt;target.directory&lt;/code&gt; as an option. It will frequently be true, so I&amp;rsquo;m going to go ahead and use it for this. We wouldn&amp;rsquo;t need to do this at all if having the text files be in the bundle was acceptable.&lt;/p&gt;
&lt;p&gt;And that brings it all together. The code generated by the plugin can be used in a package, to support an iOS app, lots of places. As long as the tool the plugin wraps will work on the machine doing the compiling, of course.&lt;/p&gt;
&lt;h2 id=&#34;other-approaches-to-data-munching&#34;&gt;Other Approaches to Data Munching&lt;/h2&gt;
&lt;p&gt;What&amp;rsquo;s good about the current approach is that when a data file changes, only the code for that data file changes. The tool will only run the once. What&amp;rsquo;s bad is that we have to add the &lt;code&gt;addCitrus()&lt;/code&gt; and &lt;code&gt;addApple()&lt;/code&gt; functions by hand and that our data storage variable loads at run time. As a note, adding &lt;em&gt;new&lt;/em&gt; files to the source code directory will trigger a rebuild and tool run every time as of Jan 2024.&lt;/p&gt;
&lt;p&gt;In &lt;a href=&#34;https://github.com/carlynorama/PluginExplorer&#34; title=&#34;PluginExplorer repo, main branch&#34;&gt;PluginExplorer&lt;/a&gt; I took a different approach. Each file didn&amp;rsquo;t get its own build command, the directory got one build command with every file listed as an input. The one and only output file actually has the &lt;code&gt;FruitStore:Dictionary&amp;lt;String,[any Fruit]&amp;gt;&lt;/code&gt; declaration which gets generated from all the files working together.&lt;/p&gt;
&lt;p&gt;in &lt;a href=&#34;https://github.com/carlynorama/PluginExplorer/blob/dev/Plugins/MyInBuildPlugin/plugin.swift&#34;&gt;plugin.swift&lt;/a&gt;&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;createBuildCommands&lt;/span&gt;(context: PackagePlugin.PluginContext, target: PackagePlugin.Target) async &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; -&amp;gt; [PackagePlugin.Command] {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//if target doesn&amp;#39;t have source files, don&amp;#39;t run the tool. &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;guard&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;target&lt;/span&gt; = target &lt;span style=&#34;color:#c6a0f6&#34;&gt;as&lt;/span&gt;? SourceModuleTarget &lt;span style=&#34;color:#c6a0f6&#34;&gt;else&lt;/span&gt; { &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; [] }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;dataDirectory&lt;/span&gt; = target.directory.appending([&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Data&amp;#34;&lt;/span&gt;]) 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;dataContents&lt;/span&gt; = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; FileManager.&lt;span style=&#34;color:#c6a0f6&#34;&gt;default&lt;/span&gt;.contentsOfDirectory(atPath: dataDirectory.string).&lt;span style=&#34;color:#91d7e3&#34;&gt;map&lt;/span&gt; { fileName &lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt; dataDirectory.appending([fileName]) }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;outputFileName&lt;/span&gt; = &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;FruitStore.swift&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;outputFiles&lt;/span&gt;:[Path] = [context.pluginWorkDirectory.appending([outputFileName])]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; [.buildCommand(displayName: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Build the FruitStore&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                                        executable: &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; context.tool(named: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;MyInBuildPluginTool&amp;#34;&lt;/span&gt;).path,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                                        arguments: [dataDirectory.string, context.pluginWorkDirectory.string, outputFileName],
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                                        inputFiles: dataContents,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                                        outputFiles: outputFiles)]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;in &lt;a href=&#34;https://github.com/carlynorama/PluginExplorer/blame/main/Sources/MyInBuildPluginTool/main.swift&#34;&gt;main.swift&lt;/a&gt;&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;///...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; (inputDir, outputDir, outputFile) = (arguments[&lt;span style=&#34;color:#f5a97f&#34;&gt;1&lt;/span&gt;], arguments[&lt;span style=&#34;color:#f5a97f&#34;&gt;2&lt;/span&gt;], arguments[&lt;span style=&#34;color:#f5a97f&#34;&gt;3&lt;/span&gt;])
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;output&lt;/span&gt; = URL(fileURLWithPath: outputDir)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;output.append(component: outputFile)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;///...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; FileManager.&lt;span style=&#34;color:#c6a0f6&#34;&gt;default&lt;/span&gt;.contentsOfDirectory(atPath: inputDir).forEach { item &lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// Did things to files here&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;///...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; generatedCode.write(to: output, atomically: &lt;span style=&#34;color:#f5a97f&#34;&gt;true&lt;/span&gt;, encoding: .utf8)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;That could potentially be a massive output file. In the future I&amp;rsquo;d like to try a hybrid approach where a &lt;code&gt;FruitStoreService()&lt;/code&gt; gets re-written for any file changes but the big load in code can happen per file. I have ideas about how to do that (two separate build plugins? One plugin with N+1 commands?), but I think I&amp;rsquo;ll wait until I have an actual application I care about at this point!&lt;/p&gt;
&lt;h2 id=&#34;summary&#34;&gt;Summary&lt;/h2&gt;
&lt;p&gt;I&amp;rsquo;m pretty excited about build plugins because they seem like in the long run they will be much easier to share than all my little bash scripts I have floating around the place. They can be in packages with &lt;a href=&#34;https://developer.apple.com/documentation/Xcode/documenting-apps-frameworks-and-packages&#34;&gt;documentation&lt;/a&gt; and &lt;a href=&#34;https://forums.swift.org/t/swift-snippets/51947&#34;&gt;snippets&lt;/a&gt; and everything. Of course that sounds awfully like a production product&amp;hellip; which is dangerous territory for this inveterate note-taker!&lt;/p&gt;
&lt;p&gt;And the notes on this topic aren&amp;rsquo;t over. Next post covers pre-build plugins and using existing tools in more details.&lt;/p&gt;
</description>
    </item>
    
    
    
    <item>
      <title>What if instead of a CLI, Plugins? Part 2, Start a Build Plugin</title>
      <link>https://whynotestflight.com/excuses/what-if-instead-of-a-cli-plugins-part-2-start-a-build-plugin/</link>
      <pubDate>Wed, 24 Jan 2024 00:00:00 +0000</pubDate>
      
      <guid>https://whynotestflight.com/excuses/what-if-instead-of-a-cli-plugins-part-2-start-a-build-plugin/</guid>
      <description>&lt;h3 id=&#34;related-repos&#34;&gt;Related Repos&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/carlynorama/BuildPluginExample&#34;&gt;https://github.com/carlynorama/BuildPluginExample&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/carlynorama/BuildPluginExampleTool&#34;&gt;https://github.com/carlynorama/BuildPluginExampleTool&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/carlynorama/PluginExplorer&#34;&gt;https://github.com/carlynorama/PluginExplorer&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;intro&#34;&gt;Intro&lt;/h2&gt;
&lt;p&gt;To write these plugins I watched the WWDC22 &lt;a href=&#34;https://developer.apple.com/videos/play/wwdc2022/110359&#34;&gt;Meet&lt;/a&gt; and &lt;a href=&#34;https://developer.apple.com/videos/play/wwdc2022/110401/&#34;&gt;Create&lt;/a&gt; videos for Package Plugins.  With respect to build plugins, they showed auto generating code based on data and generating code for image assets respectively. I combined the two to make a fictional &lt;code&gt;FruitStore&lt;/code&gt; generator.&lt;/p&gt;
&lt;p&gt;The final build script, a version of which can be seen already in the &lt;a href=&#34;https://github.com/carlynorama/PluginExplorer&#34;&gt;PluginExplorer&lt;/a&gt; repo, uses package excluded text files to generate structs and a data store &lt;code&gt;Dictionary&lt;/code&gt; that the rest of the code can refer to.&lt;/p&gt;
&lt;p&gt;As the name implies, build plugins have to be added to something that builds, so &lt;code&gt;PluginExplorer&lt;/code&gt; has its own CLI. In this walkthrough the build plugin is on its own and will be added to both a demo CLI package and a default Xcode project.&lt;/p&gt;
&lt;p&gt;This post goes from &lt;code&gt;swift package init --type build-tool-plugin&lt;/code&gt; to having a build plugin that successfully looks at text files and creates a &lt;code&gt;.swift&lt;/code&gt; file of the same name in the &lt;code&gt;.build&lt;/code&gt; folder. The rest will be in Part II of Part 2 - which will just be Part 3.&lt;/p&gt;
&lt;h2 id=&#34;getting-started&#34;&gt;Getting Started&lt;/h2&gt;
&lt;p&gt;Like with the &lt;a href=&#34;https://whynotestflight.com/excuses/what-if-instead-of-a-cli-plugins-part-1-command-plugins/&#34;&gt;command plugin&lt;/a&gt;, command line tools have been thoughtfully provided to help kick off a new project.&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;mkdir $MYPLUGINNAME
cd $MYPLUGINNAME
swift package init --type build-tool-plugin
touch README.md
# git start-repo if available (see part 1) 
git init .
git add .
git commit -m &amp;#34;Initialize repository&amp;#34;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This will create a directory structure that looks like&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-txt&#34; data-lang=&#34;txt&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;└── $MYPLUGINNAME
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    └── Plugins
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    │   └── $MYPLUGINNAME.swift
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    └── Package.swift
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    └── .git
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    └── .gitignore
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Again, the default &lt;code&gt;Package.swift&lt;/code&gt; will recognize the below layout as well.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-txt&#34; data-lang=&#34;txt&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;└── $MYPLUGINNAME
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    └── Plugins
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    │   └── $MYPLUGINNAME
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    |       └── plugin.swift
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    └── Package.swift
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    └── .git
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    └── .gitignore
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;the-default-packageswift&#34;&gt;The Default Package.swift&lt;/h3&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// swift-tools-version: 5.9&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// The swift-tools-version declares the minimum version of Swift required to build this package.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;PackageDescription&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;package&lt;/span&gt; = Package(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    name: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;$MYPLUGINNAME&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    products: [
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// Products can be used to vend plugins, making them visible to other packages.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        .plugin(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            name: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;$MYPLUGINNAME&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            targets: [&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;$MYPLUGINNAME&amp;#34;&lt;/span&gt;]),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    ],
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    targets: [
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// Targets are the basic building blocks of a package, defining a module or a test suite.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// Targets can depend on other targets in this package and products from dependencies.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        .plugin(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            name: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;$MYPLUGINNAME&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            capability: .buildTool()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        ),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    ]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;the-default-pluginswift--mypluginnameswift&#34;&gt;The Default plugin.swift / $MYPLUGINNAME.swift&lt;/h3&gt;
&lt;p&gt;This time the struct will conform to &lt;code&gt;BuildToolPlugin&lt;/code&gt;. Again, like with the &lt;a href=&#34;https://whynotestflight.com/excuses/what-if-instead-of-a-cli-plugins-part-1-command-plugins/&#34;&gt;command plugin&lt;/a&gt;, there will be a section for package code and project code.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;PackagePlugin&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;@main
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;$&lt;/span&gt;MYPLUGINNAME: BuildToolPlugin {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;/// Entry point for creating build commands for targets in Swift packages.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;createBuildCommands&lt;/span&gt;(context: PluginContext, target: Target) async &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; -&amp;gt; [Command] {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// This plugin only runs for package targets that can have source files.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;guard&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;sourceFiles&lt;/span&gt; = target.sourceModule?.sourceFiles &lt;span style=&#34;color:#c6a0f6&#34;&gt;else&lt;/span&gt; { &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; [] }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// Find the code generator tool to run (replace this with the actual one).&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;generatorTool&lt;/span&gt; = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; context.tool(named: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;my-code-generator&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// Construct a build command for each source file with a particular suffix.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; sourceFiles.&lt;span style=&#34;color:#91d7e3&#34;&gt;map&lt;/span&gt;(&lt;span style=&#34;color:#ed8796&#34;&gt;\&lt;/span&gt;.path).compactMap {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            createBuildCommand(&lt;span style=&#34;color:#c6a0f6&#34;&gt;for&lt;/span&gt;: &lt;span style=&#34;color:#f4dbd6&#34;&gt;$0&lt;/span&gt;, &lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt;: context.pluginWorkDirectory, with: generatorTool.path)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#if&lt;/span&gt; &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;canImport&lt;/span&gt;(&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;XcodeProjectPlugin&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;XcodeProjectPlugin&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;extension&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;$&lt;/span&gt;MYPLUGINNAME: XcodeBuildToolPlugin {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// Entry point for creating build commands for targets in Xcode projects.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;createBuildCommands&lt;/span&gt;(context: XcodePluginContext, target: XcodeTarget) &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; -&amp;gt; [Command] {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// Find the code generator tool to run (replace this with the actual one).&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;generatorTool&lt;/span&gt; = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; context.tool(named: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;my-code-generator&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// Construct a build command for each source file with a particular suffix.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; target.inputFiles.&lt;span style=&#34;color:#91d7e3&#34;&gt;map&lt;/span&gt;(&lt;span style=&#34;color:#ed8796&#34;&gt;\&lt;/span&gt;.path).compactMap {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            createBuildCommand(&lt;span style=&#34;color:#c6a0f6&#34;&gt;for&lt;/span&gt;: &lt;span style=&#34;color:#f4dbd6&#34;&gt;$0&lt;/span&gt;, &lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt;: context.pluginWorkDirectory, with: generatorTool.path)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#endif&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;extension&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;$&lt;/span&gt;MYPLUGINNAME {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;/// Shared function that returns a configured build command if the input files is one that should be processed.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;createBuildCommand&lt;/span&gt;(&lt;span style=&#34;color:#c6a0f6&#34;&gt;for&lt;/span&gt; inputPath: Path, &lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt; outputDirectoryPath: Path, with generatorToolPath: Path) -&amp;gt; Command? {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// Skip any file that doesn&amp;#39;t have the extension we&amp;#39;re looking for (replace this with the actual one).&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;guard&lt;/span&gt; inputPath.&lt;span style=&#34;color:#ed8796&#34;&gt;extension&lt;/span&gt; == &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;my-input-suffix&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;else&lt;/span&gt; { &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; .&lt;span style=&#34;color:#c6a0f6&#34;&gt;none&lt;/span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// Return a command that will run during the build to generate the output file.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;inputName&lt;/span&gt; = inputPath.lastComponent
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;outputName&lt;/span&gt; = inputPath.stem &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;+&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;.swift&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;outputPath&lt;/span&gt; = outputDirectoryPath.appending(outputName)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; .buildCommand(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            displayName: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Generating &lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;outputName&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt; from &lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;inputName&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            executable: generatorToolPath,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            arguments: [&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;inputPath&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;-o&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;outputPath&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;],
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            inputFiles: [inputPath],
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            outputFiles: [outputPath]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        )
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;make-test-package&#34;&gt;Make Test Package&lt;/h2&gt;
&lt;p&gt;My build plugin won&amp;rsquo;t work on just any old project. It will only work on projects with the right files. So lets make one. I&amp;rsquo;m going to assume general comfort around CLI projects, but here&amp;rsquo;s some getting started help.&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;mkdir $DEMOPACKAGE
cd $DEMOPACKAGE
swift package init --type tool
swift run
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Change contents of &lt;code&gt;Sources/$DEMOPACKAGE.swift&lt;/code&gt; to&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//  $DEMOPACKAGE.swift&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//  Created by Carlyn Maw on 1/17/24.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;ArgumentParser&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;@main
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;$&lt;/span&gt;DEMOPACKAGE: AsyncParsableCommand {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;configuration&lt;/span&gt; = CommandConfiguration(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        abstract: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;For Testing The Plugins&amp;#34;&lt;/span&gt;, 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        version: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;0.0.0&amp;#34;&lt;/span&gt;, 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        subcommands: [hello.&lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;, fruit_list.&lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;], 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        defaultSubcommand: hello.&lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;hello&lt;/span&gt;: ParsableCommand {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;mutating&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;run&lt;/span&gt;() &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Hello, world!&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Switching up the structure will allow us to make different tests as separate parsable commands as needed.&lt;/p&gt;
&lt;h3 id=&#34;update-the-packageswift-to-include-the-build-plugin&#34;&gt;Update the Package.swift to Include the Build Plugin&lt;/h3&gt;
&lt;p&gt;Add the build plugin to the &lt;strong&gt;&lt;code&gt;plugins&lt;/code&gt;&lt;/strong&gt; parameter of the executable target. NOT the dependencies. Doing otherwise can &lt;a href=&#34;https://github.com/apple/swift-package-manager/issues/6676&#34;&gt;cause linker errors&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;In this specific case the package containing the plugin and and the plugin itself have the same name and the folder containing it may or may not.&lt;/p&gt;
&lt;p&gt;As a general rule, the name of the package and the folder enclosing it should be the same. The &lt;code&gt;name&lt;/code&gt; parameter is more of a &lt;code&gt;displayName&lt;/code&gt; and in many places the code looks to the enclosing folder to get its identity. When using URLs to include projects this becomes all the more key. Keep this in mind when designing your own packages.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// swift-tools-version: 5.9&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// The swift-tools-version declares the minimum version of Swift required to build this package.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;PackageDescription&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;package&lt;/span&gt; = Package(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    name: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;$DEMOPACKAGE&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    dependencies: [
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        .package(url: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;https://github.com/apple/swift-argument-parser.git&amp;#34;&lt;/span&gt;, from: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;1.2.0&amp;#34;&lt;/span&gt;),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        .package(name: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;$MYPLUGINNAME&amp;#34;&lt;/span&gt;, path: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;../PATH/TO/PLUGIN/FOLDER/INCLUSIVE&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    ],
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    targets: [
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        .executableTarget(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            name: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;DemoFruitStore&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            dependencies: [
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                .product(name: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;ArgumentParser&amp;#34;&lt;/span&gt;, package: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;swift-argument-parser&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//NOT HERE !!! .product(name: , package: &amp;#34;FruitStoreBuild&amp;#34;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            ],
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            plugins: [
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//HERE!!&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                .plugin(name: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;FruitStoreBuild&amp;#34;&lt;/span&gt;, package: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;FruitStoreBuild&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            ] 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        ),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    ]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;building-a-custom-tool&#34;&gt;Building a Custom Tool&lt;/h2&gt;
&lt;p&gt;If you run &amp;ldquo;$DEMOPACKAGE&amp;rdquo; now (&lt;code&gt;swift run&lt;/code&gt; in the root folder should still work) hopefully you&amp;rsquo;ll get the following error:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;error: Plugin does not have access to a tool named ‘my-code-generator’
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;error: build stopped due to build-tool plugin failures
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;error: Plugin does not have access to a tool named ‘my-code-generator’
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;error: build stopped due to build-tool plugin failures
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The lines in the way of a successful run are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;line 11: &lt;code&gt;let generatorTool = try context.tool(named: &amp;quot;my-code-generator&amp;quot;)&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;line 27: &lt;code&gt;let generatorTool = try context.tool(named: &amp;quot;my-code-generator&amp;quot;)&lt;/code&gt; again&lt;/li&gt;
&lt;li&gt;line 42: &lt;code&gt;guard inputPath.extension == &amp;quot;my-input-suffix&amp;quot; else { return .none }&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;line 51: &lt;code&gt;arguments: [&amp;quot;\(inputPath)&amp;quot;, &amp;quot;-o&amp;quot;, &amp;quot;\(outputPath)&amp;quot;],&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;11, 27 and 51 all go hand in hand. Unlike with the command plugin example we&amp;rsquo;re not going to import an external tool, we&amp;rsquo;re going to build it.&lt;/p&gt;
&lt;h2 id=&#34;make-the-tool&#34;&gt;Make the Tool&lt;/h2&gt;
&lt;p&gt;From the root directory of the $MYPLUGINNAME project folder:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;mkdir Sources
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;mkdir Sources/MyPluginNameTool
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;touch Sources/MyPluginNameTool/main.swift
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;update-packageswift&#34;&gt;Update Package.swift&lt;/h3&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// swift-tools-version: 5.9&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// The swift-tools-version declares the minimum version of Swift required to build this package.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;PackageDescription&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;package&lt;/span&gt; = Package(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    name: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;$MYPLUGINNAME&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    products: [
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// Products can be used to vend plugins, making them visible to other packages.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        .plugin(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            name: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;$MYPLUGINNAME&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            targets: [&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;$MYPLUGINNAME&amp;#34;&lt;/span&gt;]),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    ],
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    targets: [
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// Targets are the basic building blocks of a package, defining a module or a test suite.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// Targets can depend on other targets in this package and products from dependencies.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        .executableTarget(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            name: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;my-code-generator&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            path: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Sources/MyPluginNameTool&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        ),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        .plugin(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            name: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;$MYPLUGINNAME&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            capability: .buildTool(),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            dependencies: [&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;my-code-generator&amp;#34;&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        ),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    ]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;add-content-to-mainswift&#34;&gt;Add content to main.swift&lt;/h3&gt;
&lt;p&gt;Add code to &lt;code&gt;main.swift&lt;/code&gt; that will compliment the arguments from line 52.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;Foundation&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;arguments&lt;/span&gt; = ProcessInfo().arguments
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; arguments.&lt;span style=&#34;color:#91d7e3&#34;&gt;count&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;lt;&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;4&lt;/span&gt; {              &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//&amp;lt;== Number of arguments sample code will send. &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;missing arguments&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;ARGUMENTS&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;arguments.forEach {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(&lt;span style=&#34;color:#f4dbd6&#34;&gt;$0&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;update-pluginswift&#34;&gt;Update plugin.swift&lt;/h3&gt;
&lt;p&gt;Change line 42 from&lt;/p&gt;
&lt;p&gt;&lt;code&gt;guard inputPath.extension == &amp;quot;my-input-suffix&amp;quot; else { return .none }&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;to&lt;/p&gt;
&lt;p&gt;&lt;code&gt;guard inputPath.extension == &amp;quot;swift&amp;quot; else { return .none }&lt;/code&gt;&lt;/p&gt;
&lt;h3 id=&#34;check-the-tool&#34;&gt;Check the Tool&lt;/h3&gt;
&lt;p&gt;Run &amp;ldquo;$DEMOPACKAGE&amp;rdquo;. You may have to clear the .build folder, but eventually you should get the following print out&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Building &lt;span style=&#34;color:#c6a0f6&#34;&gt;for&lt;/span&gt; debugging...
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ARGUMENTS
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;{&lt;/span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;$PATH_TO_REPO&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;}&lt;/span&gt;/DemoPackage/.build/plugins/tools/debug/my-code-generator
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;{&lt;/span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;$PATH_TO_REPO&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;}&lt;/span&gt;/DemoPackage/Sources/DemoPackage.swift
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;-o
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;{&lt;/span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;$PATH_TO_REPO&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;}&lt;/span&gt;/DemoPackage/.build/plugins/outputs/DemoPackage/DemoPackage/MyPluginName/DemoPackage.swift
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;error: filename &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;DemoPackage.swift&amp;#34;&lt;/span&gt; used twice: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#39;{$PATH_TO_REPO}/DemoPackage/Sources/DemoPackage.swift&amp;#39;&lt;/span&gt; and &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#39;{$PATH_TO_REPO}/DemoPackage/.build/plugins/outputs/DemoPackage/DemoPackage/MyPluginName/DemoPackage.swift&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;note: filenames are used to distinguish private declarations with the same name
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Lets break them down. First we get the print out of the arguments:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;0: the tool itself&lt;/li&gt;
&lt;li&gt;1: the path to the input file&lt;/li&gt;
&lt;li&gt;2: a flag &amp;ldquo;-o&amp;rdquo; typically used to indicate what follows is an output file path that should overwrite the defaults.&lt;/li&gt;
&lt;li&gt;3: that output path.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Then we get a warning about duplicate files??? What duplicate files?? I didn&amp;rsquo;t actually do anything?&lt;/p&gt;
&lt;p&gt;The in-build plugin infrastructure keep tabs on the inputs and the outputs because in-build plugins only run when those inputs and outputs are stale. Even though we didn&amp;rsquo;t actually generate the output file the the &lt;code&gt;Command&lt;/code&gt; generated in &lt;code&gt;createBuildCommand&lt;/code&gt; told the infrastructure it means to, and the infrastructure thinks that&amp;rsquo;s a bad idea.&lt;/p&gt;
&lt;p&gt;Print statements from the build command&amp;rsquo;s tool end up in the terminal. Print statements from within &lt;code&gt;createBuildCommand&lt;/code&gt; DO NOT appear unless &amp;ldquo;very verbose&amp;rdquo; mode was chosen, i.e. &lt;code&gt;swift run -vv&lt;/code&gt;. Messages to &lt;code&gt;stderr&lt;/code&gt; instead of &lt;code&gt;stdout&lt;/code&gt; do appear.&lt;/p&gt;
&lt;h2 id=&#34;what-happens-in-xcode&#34;&gt;What Happens in Xcode?&lt;/h2&gt;
&lt;p&gt;It takes two steps to load a plugin into an Xcode project:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Adding the package to the project&lt;/li&gt;
&lt;li&gt;Navigating to the specific &lt;code&gt;Target&lt;/code&gt;info panel and adding it to the build phases.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This process is visible in &lt;a href=&#34;https://developer.apple.com/videos/play/wwdc2023/10171/?time=475&#34;&gt;Meet Swift OpenAPI Generator&lt;/a&gt; at minute 8.&lt;/p&gt;
&lt;p&gt;I made a default multi-platform app called  &lt;code&gt;PluginTesterApp&lt;/code&gt;. Here is a screenshot of adding the build plugin to the build phase of the app target.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;build_phase.png&#34; alt=&#34;Build Phase Screenshot&#34;&gt;&lt;/p&gt;
&lt;p&gt;In Xcode the build will FAIL with one message per &lt;code&gt;.swift&lt;/code&gt; file in the Target.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Multiple commands produce &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#39;/Users/MaybeYou/Library/Developer/Xcode/DerivedData/PluginTesterApp-alhhewcaqznpzedyonljgielnmmv/Build/Intermediates.noindex/PluginTesterApp.build/Debug-iphonesimulator/PluginTesterApp.build/Objects-normal/arm64/ContentView.stringsdata&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Multiple commands produce &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#39;/Users/Carlyn/Library/Developer/Xcode/DerivedData/PluginTesterApp-alhhewcaqznpzedyonljgielnmmv/Build/Intermediates.noindex/PluginTesterApp.build/Debug-iphonesimulator/PluginTesterApp.build/Objects-normal/arm64/PluginTesterAppApp.stringsdata&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;More details will be visible in the &amp;ldquo;Report navigator&amp;rdquo;. There the print statements from within &lt;code&gt;createBuildCommand&lt;/code&gt; will be visible, but unlike what happened with the package there will be no indication that the &lt;code&gt;my-code-generator&lt;/code&gt; tool ran because Xcode halted everything when confronted with the conflict.&lt;/p&gt;
&lt;h3 id=&#34;fix-the-conflict&#34;&gt;Fix the conflict&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Add an &lt;code&gt;apple.txt&lt;/code&gt; file to the &lt;code&gt;PluginTesterApp&lt;/code&gt; target in &lt;code&gt;PluginTesterApp&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;change line 42 in plugin.swift to:
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;guard inputPath.extension == &amp;quot;txt&amp;quot; else { return .none }&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;add &lt;code&gt;print(&amp;quot;PROOF OF PLUGIN LIFE from createBuildCommand&amp;quot;)&lt;/code&gt; right below it.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If those changes were made an external editor, right click on the plugin package in the &amp;ldquo;Project navigator&amp;rdquo; and select &amp;ldquo;Update Package&amp;rdquo; to see the changes. If that doesn&amp;rsquo;t clear any problems up, Shift + Cmd + K to clean the build folder.&lt;/p&gt;
&lt;p&gt;Xcode will fail to build again, but we can see from the &amp;ldquo;Report navigator&amp;rdquo; it isn&amp;rsquo;t because our script didn&amp;rsquo;t run this time. Both the print statements from the plugin and the plugin embedded tool are visible in the reports at but in different places. The plugin code runs at the beginning of the build. The tool will run when its appropriate to the build process.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;xcode_build_report.png&#34; alt=&#34;Screenshot of Reports Navigator with a build report selected. It shows the print statements from main.swift&#34;&gt;&lt;/p&gt;
&lt;p&gt;The errors now come from the fact that we promised our code there would be an &lt;code&gt;apple.swift&lt;/code&gt; file somewhere and we didn&amp;rsquo;t actually make one. Every file when it gets complied complains:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Error opening input file &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#39;/Users/MaybeYou/Library/Developer/Xcode/DerivedData/PluginTesterApp-alhhewcaqznpzedyonljgielnmmv/SourcePackages/plugins/PluginTesterApp.output/PluginTesterApp/MyPluginName/apple.swift&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;(&lt;/span&gt;No such file or directory&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This file is supposed to be in the build folder of our enclosing App. The tool gets the path to the build folder from &lt;code&gt;context.pluginWorkDirectory&lt;/code&gt; in &lt;code&gt;plugin.swift&lt;/code&gt; (line 15 for the package and 31 for the project).&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; sourceFiles.&lt;span style=&#34;color:#91d7e3&#34;&gt;map&lt;/span&gt;(&lt;span style=&#34;color:#ed8796&#34;&gt;\&lt;/span&gt;.path).compactMap {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            createBuildCommand(&lt;span style=&#34;color:#c6a0f6&#34;&gt;for&lt;/span&gt;: &lt;span style=&#34;color:#f4dbd6&#34;&gt;$0&lt;/span&gt;, &lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt;: context.pluginWorkDirectory, with: generatorTool.path)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Lets make one.&lt;/p&gt;
&lt;h3 id=&#34;update-mainswift-run-project-again&#34;&gt;Update main.swift, run project again.&lt;/h3&gt;
&lt;p&gt;Update &lt;code&gt;main.swift&lt;/code&gt; to actually save that &lt;code&gt;.swift&lt;/code&gt; file the &lt;code&gt;Command&lt;/code&gt; promised. The contents of every Swift file made will be a single line comment for now.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;Foundation&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;arguments&lt;/span&gt; = ProcessInfo().arguments
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; arguments.&lt;span style=&#34;color:#91d7e3&#34;&gt;count&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;lt;&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;4&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;missing arguments&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// print(&amp;#34;ARGUMENTS&amp;#34;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// arguments.forEach {&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//     print($0)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// }&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; (input, output) = (arguments[&lt;span style=&#34;color:#f5a97f&#34;&gt;1&lt;/span&gt;], arguments[&lt;span style=&#34;color:#f5a97f&#34;&gt;3&lt;/span&gt;])
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//Added for ease of scanning for our output.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;FIIIIIIIIIIIIIINNNNNNNNNDDDMMMEEEEEEEEEEEEEEEEE&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;from MyBuildPluginTool:&amp;#34;&lt;/span&gt;, input)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;from MyBuildPluginTool:&amp;#34;&lt;/span&gt;, output)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;outputURL&lt;/span&gt; = URL(fileURLWithPath: output)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;contentsOfFile&lt;/span&gt; = &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;//nothing of importance&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; contentsOfFile.write(to: outputURL, atomically: &lt;span style=&#34;color:#f5a97f&#34;&gt;true&lt;/span&gt;, encoding: .utf8)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Clean the build folder and run the project again. It should work without error this time.&lt;/p&gt;
&lt;h3 id=&#34;meanwhile-back-in-the-package&#34;&gt;Meanwhile back in the package&amp;hellip;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;add an &lt;code&gt;apple.txt&lt;/code&gt; to the package (&lt;code&gt;touch Sources/Data/banana.txt&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;swift run&lt;/code&gt; again will show the output from the tool but not the plugin code
&lt;ul&gt;
&lt;li&gt;`from MyBuildPluginTool:`` print statements will show&lt;/li&gt;
&lt;li&gt;&lt;code&gt;&amp;quot;PROOF OF PLUGIN LIFE from createBuildCommand&amp;quot;&lt;/code&gt; will not unless running in &amp;ndash;vv mode.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The result will look something like&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;warning: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#39;demopackage&amp;#39;&lt;/span&gt;: found &lt;span style=&#34;color:#f5a97f&#34;&gt;1&lt;/span&gt; file&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;(&lt;/span&gt;s&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;)&lt;/span&gt; which are unhandled; explicitly &lt;span style=&#34;color:#91d7e3&#34;&gt;declare&lt;/span&gt; them as resources or exclude from the target
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;{&lt;/span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;$PATH_TO_REPO&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;}&lt;/span&gt;/DemoPackage/Sources/apple.txt
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Building &lt;span style=&#34;color:#c6a0f6&#34;&gt;for&lt;/span&gt; debugging...
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;[&lt;/span&gt;3/3&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;]&lt;/span&gt; Linking my-code-generator
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Build complete! &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;(&lt;/span&gt;1.29s&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Building &lt;span style=&#34;color:#c6a0f6&#34;&gt;for&lt;/span&gt; debugging...
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;FIIIIIIIIIIIIIINNNNNNNNNDDDMMMEEEEEEEEEEEEEEEEE
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;from MyBuildPluginTool: &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;{&lt;/span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;$PATH_TO_REPO&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;}&lt;/span&gt;/DemoPackage/Sources/apple.txt
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;from MyBuildPluginTool: &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;{&lt;/span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;$PATH_TO_REPO&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;}&lt;/span&gt;/DemoPackage/.build/plugins/outputs/demopackage/DemoPackage/MyPluginName/apple.swift
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;[&lt;/span&gt;5/5&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;]&lt;/span&gt; Linking DemoPackage
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Build complete! &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;(&lt;/span&gt;2.68s&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Hello, world!
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;To check if it worked &lt;code&gt;ls&lt;/code&gt; the build directory then &lt;code&gt;cat&lt;/code&gt; the file:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ls /Users/.../.build/.../MyPluginName/
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;cat /Users/.../.build/.../MyPluginName/apple.swift
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The easiest thing to do is to match up to Xcode&amp;rsquo;s behavior and &lt;a href=&#34;https://developer.apple.com/documentation/xcode/bundling-resources-with-a-swift-package&#34;&gt;call it a Resource&lt;/a&gt;. Using the &lt;code&gt;.process&lt;/code&gt; descriptor means that the file will be examined and Swift Package Manger will make its best call about whether the file should be optimized or copied as is.  If curious, the &lt;a href=&#34;https://whynotestflight.com/excuses/what-if-instead-of-a-cli-plugins-part-1-command-plugins/&#34;&gt;command plugin from the last post&lt;/a&gt; can confirm that Xcode is calling it a resource with a swap in of &lt;code&gt;target.inputFiles.filter({$0.type == .resource})&lt;/code&gt; in the Xcode project source files section.&lt;/p&gt;
&lt;p&gt;Update Package.swift&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        .executableTarget(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            name: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;DemoFruitStore&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            dependencies: [
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                .product(name: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;ArgumentParser&amp;#34;&lt;/span&gt;, package: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;swift-argument-parser&amp;#34;&lt;/span&gt;),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            ],
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            resources: [
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                .process(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;apple.txt&amp;#34;&lt;/span&gt;) &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//if a directory, `.process(&amp;#34;DirName&amp;#34;)` works fine.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            ],
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            plugins: [
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                .plugin(name: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;MyPluginName&amp;#34;&lt;/span&gt;, package: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;MyPluginName&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            ] 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        ),
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This will silence the warning and our code still works just fine.&lt;/p&gt;
&lt;p&gt;HOWEVER this means we will now have a copy of this file in the bundle, which we did not have before.&lt;/p&gt;
&lt;p&gt;To verify, from the same working directory as &lt;code&gt;swift run&lt;/code&gt; try &lt;code&gt;find .build/ -name &amp;quot;apple.txt&amp;quot;&lt;/code&gt; both before and after updating the package file. Do the same on the Xcode project build folder reveals it too hides an &lt;code&gt;apple.txt&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Instead we want to EXCLUDE our text files since they aren&amp;rsquo;t used by anything other than the build process.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        .executableTarget(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            name: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;DemoPackage&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            dependencies: [
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                .product(name: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;ArgumentParser&amp;#34;&lt;/span&gt;, package: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;swift-argument-parser&amp;#34;&lt;/span&gt;),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            ],
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            exclude: [
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;apple.txt&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//if a directory - `&amp;#34;DirName&amp;#34;` works fine. &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            ],
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            plugins: [
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                .plugin(name: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;MyPluginName&amp;#34;&lt;/span&gt;, package: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;MyPluginName&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            ]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        ),
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This time check &lt;code&gt;find .build/ -name &amp;quot;apple.swift&amp;quot;&lt;/code&gt; There won&amp;rsquo;t be one. Our package version of the build plugin checks source code only, and we&amp;rsquo;ve just excluded &amp;ldquo;apple.txt&amp;rdquo; from being source code.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;MYPLUGINNAME/plugin.swift&lt;/code&gt; line 8 has the relevant code.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;guard&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;sourceFiles&lt;/span&gt; = target.sourceModule?.sourceFiles &lt;span style=&#34;color:#c6a0f6&#34;&gt;else&lt;/span&gt; { &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; [] } 
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This line inside the &lt;code&gt;createBuildCommands&lt;/code&gt; function ensures that the target module has source files and then hands them over.&lt;/p&gt;
&lt;p&gt;Replace the &lt;code&gt;createBuildCommands&lt;/code&gt; function for the package with:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//Add `import Foundation` to the top of the file because of FileManger&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;createBuildCommands&lt;/span&gt;(context: PluginContext, target: Target) async &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; -&amp;gt; [Command] {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// Find the code generator tool to run (This is what we named our actual one.).&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;generatorTool&lt;/span&gt; = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; context.tool(named: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;my-code-generator&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// Still ensures that the target is a source module.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;guard&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;target&lt;/span&gt; = target &lt;span style=&#34;color:#c6a0f6&#34;&gt;as&lt;/span&gt;? SourceModuleTarget &lt;span style=&#34;color:#c6a0f6&#34;&gt;else&lt;/span&gt; { &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; [] }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// Get the source directory of the target&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;dataDirectory&lt;/span&gt; = target.directory
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// Get all the files in that directory, source file or not.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;allSourceFiles&lt;/span&gt; = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; FileManager.&lt;span style=&#34;color:#c6a0f6&#34;&gt;default&lt;/span&gt;.contentsOfDirectory(at: dataDirectory).&lt;span style=&#34;color:#91d7e3&#34;&gt;map&lt;/span&gt; { fileName &lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                dataDirectory.appending([fileName])
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// Construct a build command for each source file with a particular suffix.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; allSourceFiles.compactMap(&lt;span style=&#34;color:#ed8796&#34;&gt;\&lt;/span&gt;.path).compactMap {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            createBuildCommand(&lt;span style=&#34;color:#c6a0f6&#34;&gt;for&lt;/span&gt;: &lt;span style=&#34;color:#f4dbd6&#34;&gt;$0&lt;/span&gt;, &lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt;: context.pluginWorkDirectory, with: generatorTool.path)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;find .build/ -name &amp;quot;apple.*&amp;quot;&lt;/code&gt; will show quite a few files, one of them will be the generated &lt;code&gt;apple.swift&lt;/code&gt;, the others will be products generated from it&amp;hellip; but there will be NO &lt;code&gt;apple.txt&lt;/code&gt;!&lt;/p&gt;
&lt;h4 id=&#34;look-a-little-deeper&#34;&gt;Look a Little Deeper&lt;/h4&gt;
&lt;p&gt;&lt;code&gt;FileManager.default.contentsOfDirectory(atPath: dataDirectory.string)&lt;/code&gt; is NOT recursive. To make an optionally recursive directory search one could do something like&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;filesFromDirectory&lt;/span&gt;(path providedPath:Path, shallow:&lt;span style=&#34;color:#91d7e3&#34;&gt;Bool&lt;/span&gt; = &lt;span style=&#34;color:#f5a97f&#34;&gt;true&lt;/span&gt;) &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; -&amp;gt; [Path] {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; shallow {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; FileManager.&lt;span style=&#34;color:#c6a0f6&#34;&gt;default&lt;/span&gt;.contentsOfDirectory(atPath: providedPath.string).compactMap { fileName &lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            providedPath.appending([fileName])
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    } &lt;span style=&#34;color:#c6a0f6&#34;&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;dataDirectoryURL&lt;/span&gt; = URL(fileURLWithPath: providedPath.string, isDirectory: &lt;span style=&#34;color:#f5a97f&#34;&gt;true&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;allFiles&lt;/span&gt; = [Path?]()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;enumerator&lt;/span&gt; = FileManager.&lt;span style=&#34;color:#c6a0f6&#34;&gt;default&lt;/span&gt;.enumerator(at: dataDirectoryURL, includingPropertiesForKeys: [.isRegularFileKey], options: [.skipsHiddenFiles, .skipsPackageDescendants])
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;while&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;fileURL&lt;/span&gt; = enumerator?.nextObject() &lt;span style=&#34;color:#c6a0f6&#34;&gt;as&lt;/span&gt;? URL {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;regularFileCheck&lt;/span&gt; = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; fileURL.resourceValues(forKeys:[.isRegularFileKey]).isRegularFile, regularFileCheck == &lt;span style=&#34;color:#f5a97f&#34;&gt;true&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                allFiles.append((Path(fileURL.path())))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; allFiles.compactMap({&lt;span style=&#34;color:#f4dbd6&#34;&gt;$0&lt;/span&gt;})
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;In production it&amp;rsquo;d be cleaner to have a non recursive search of the specific directory of relevant files along the lines &lt;code&gt;let dataDirectory = target.directory.appending([&amp;quot;Data&amp;quot;])&lt;/code&gt;&lt;/p&gt;
&lt;h3 id=&#34;what-about-excluding-in-xcode&#34;&gt;What About Excluding in XCode?&lt;/h3&gt;
&lt;p&gt;As mentioned above Xcode considers files added to it with File &amp;gt; Add as resources by default.&lt;/p&gt;
&lt;p&gt;To remove the file from all targets using the GUI:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;click on &lt;code&gt;apple.txt&lt;/code&gt; in the Navigator,&lt;/li&gt;
&lt;li&gt;make sure the Inspector area is on &amp;ldquo;file Inspector&amp;rdquo;&lt;/li&gt;
&lt;li&gt;and uncheck any boxes under &amp;ldquo;Target Membership&amp;rdquo;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If those words don&amp;rsquo;t feel familiar check out the documentation on &lt;a href=&#34;https://developer.apple.com/documentation/xcode/configuring-the-xcode-project-window&#34;&gt;how to configure an Xcode Window&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;With the check boxes unchecked, &lt;code&gt;apple.txt&lt;/code&gt; disappears from the file list available to the build plugin entirely. Clean the build folder to remove the warnings about the stale &lt;code&gt;apple.swift&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Unfortunately in the &lt;code&gt;XcodeCommandPlugin&lt;/code&gt; side of things, &lt;code&gt;target.directory&lt;/code&gt; is not a thing. However &lt;code&gt;context.xcodeProject.directory&lt;/code&gt; does exist and so does &lt;code&gt;target.displayName&lt;/code&gt; and so does &lt;code&gt;inputFiles&lt;/code&gt;. Between those three something can be done to get the files we need.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ll show this working with the rest of the code in the next post.&lt;/p&gt;
&lt;h2 id=&#34;so-when-exactly-do-the-tools-run&#34;&gt;So when exactly do the tools run?&lt;/h2&gt;
&lt;p&gt;In our package the build plugin will now run every time a new file OF ANY TYPE gets added to the Sources directory.  That will then kick of the tool running for each text file, regardless if the text file has changed. When a &lt;code&gt;.txt&lt;/code&gt; changes, the tool will run for that file alone.&lt;/p&gt;
&lt;p&gt;It makes sense that the build plugin would refresh when the file list changes. If the list of relevant files hasn&amp;rsquo;t changed, I&amp;rsquo;m not sure why it reruns the tool on the unchanged files.&lt;/p&gt;
&lt;p&gt;In Xcode it appears to be running every time. Which is also not what I expected.&lt;/p&gt;
&lt;p&gt;That said, I&amp;rsquo;d rather the things run more than less and it&amp;rsquo;s questionable to be storing ginormous files unneeded in the final build in with the source anyway.&lt;/p&gt;
&lt;h2 id=&#34;to-be-continued&#34;&gt;TO BE CONTINUED&lt;/h2&gt;
&lt;p&gt;At this point we have a build plugin that can find the wanted files and run a tool over them to create new files for the build.&lt;/p&gt;
&lt;p&gt;Doing something actually useful? That&amp;rsquo;s for another day!&lt;/p&gt;
</description>
    </item>
    
    
    
    <item>
      <title>What if instead of a CLI, Plugins? Part 1, Command plugins</title>
      <link>https://whynotestflight.com/excuses/what-if-instead-of-a-cli-plugins-part-1-command-plugins/</link>
      <pubDate>Sat, 20 Jan 2024 00:00:00 +0000</pubDate>
      
      <guid>https://whynotestflight.com/excuses/what-if-instead-of-a-cli-plugins-part-1-command-plugins/</guid>
      <description>&lt;h3 id=&#34;related-repos&#34;&gt;Related Repos&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/carlynorama/BuildPluginExample&#34;&gt;https://github.com/carlynorama/BuildPluginExample&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/carlynorama/BuildPluginExampleTool&#34;&gt;https://github.com/carlynorama/BuildPluginExampleTool&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/carlynorama/PluginExplorer&#34;&gt;https://github.com/carlynorama/PluginExplorer&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I like writing little command line utilities to make my life easier. &lt;a href=&#34;https://www.swift.org/package-manager/&#34;&gt;Swift Package Manager&lt;/a&gt; has developed a &lt;a href=&#34;https://github.com/apple/swift-package-manager/blob/main/Documentation/Plugins.md&#34;&gt;plugin system&lt;/a&gt; which makes those tools easier to reuse across projects. The tools can be incorporated into the build process, before or during. They can also run on demand.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;run on demand: command plugin (this post)&lt;/li&gt;
&lt;li&gt;run only if resources are missing or stale: build plugin (&lt;a href=&#34;https://whynotestflight.com/excuses/what-if-instead-of-a-cli-plugins-part-2-start-a-build-plugin/&#34;&gt;part 2&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;run every build, before the build: pre-build plugin&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I wrote one of each. This post covers the intro and command plugins. The &lt;a href=&#34;https://github.com/carlynorama/PluginExplorer&#34;&gt;related repo&lt;/a&gt; already has all three. It has an integrated CLI to test build scripts and wasn&amp;rsquo;t designed to import into non-package projects from the outset but I&amp;rsquo;m converting it. I will cover how to make Xcode project compatible plugins from the outset in the write up though.  To be clear, package plugins ARE available in in Xcode when a package has them as a dependency. You just can&amp;rsquo;t use package plugins directly on iOS apps, etc.&lt;/p&gt;
&lt;p&gt;While I do describe how to run plugins, I do not include a lot of screen shots. For more details watch:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;WWDC 2022 &lt;a href=&#34;https://developer.apple.com/videos/play/wwdc2022/110359&#34;&gt;Meet Swift Package plugins&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;WWDC 2022 &lt;a href=&#34;https://developer.apple.com/videos/play/wwdc2022/110401/&#34;&gt;Create Swift Package plugins&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Also, to help with descriptions: &lt;a href=&#34;https://developer.apple.com/documentation/xcode/configuring-the-xcode-project-window&#34;&gt;Xcode Window Terminology&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&#34;handy-commands-for-running-command-plugins&#34;&gt;Handy Commands For Running Command Plugins&lt;/h2&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;swift package plugin --list
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;swift package &lt;span style=&#34;color:#f4dbd6&#34;&gt;$PLUGIN_VERB&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;swift package --allow-writing-to-package-directory &lt;span style=&#34;color:#f4dbd6&#34;&gt;$PLUGIN_VERB&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;swift package clean &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#in lieu of deleting the .build folder as needed&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;handy-commands-for-generating-projects&#34;&gt;Handy Commands for Generating Projects&lt;/h2&gt;
&lt;p&gt;This is for 5.9, More options/flags will be available in 5.10 it looks like.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;swift package init --type tool &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#Comes with argument parser&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;swift package init --type build-tool-plugin
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;swift package init --type command-plugin
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;misc-gotchas-for-all-three-types&#34;&gt;Misc Gotchas for All Three Types&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Code generated by build plugins is generally detectable by IDE&amp;rsquo;s, but the build tool has to have been run at least once before you can use it.&lt;/li&gt;
&lt;li&gt;Code only associated with a &lt;code&gt;.plugin&lt;/code&gt; target doesn&amp;rsquo;t get &lt;a href=&#34;https://forums.swift.org/t/package-command-plugins-cant-see-plugin-targets/69439&#34;&gt;swept up in targets&lt;/a&gt;, and build problems can only be found in the build logs. Code in a stand alone tool imported by the plugin does get more regular treatment. Prioritize putting as much as possible into a tool and as little a possible only in a plugin.swift.&lt;/li&gt;
&lt;li&gt;Write the tool and get it completely working, then write the plugin.&lt;/li&gt;
&lt;li&gt;stdout for a tool does not always &lt;a href=&#34;https://forums.swift.org/t/where-does-the-happy-path-output-stdout-from-a-prebuild-plugin-tool-using-an-external-binary-go-how-do-i-see-it/69520&#34;&gt;work as expected&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;For two plugins to share code they need to both depend on the same executable target or a binary, not a private target. &lt;a href=&#34;https://forums.swift.org/t/difficulty-sharing-code-between-swift-package-manager-plugins/61690/3&#34;&gt;See discussion&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Adding new files to the source directory is expensive to build plugins. It will rerun not just the plugin, but regenerate every command and run the tool(s).&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;references&#34;&gt;References&lt;/h2&gt;
&lt;h3 id=&#34;official&#34;&gt;Official&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;WWDC 2022 &lt;a href=&#34;https://developer.apple.com/videos/play/wwdc2022/110359&#34;&gt;Meet Swift Package plugins&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;WWDC 2022 &lt;a href=&#34;https://developer.apple.com/videos/play/wwdc2022/110401/&#34;&gt;Create Swift Package plugins&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/apple/swift-package-manager/&#34;&gt;https://github.com/apple/swift-package-manager/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://forums.swift.org/t/pitch-package-manager-command-plugins/53172&#34;&gt;https://forums.swift.org/t/pitch-package-manager-command-plugins/53172&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/apple/swift-evolution/blob/main/proposals/0303-swiftpm-extensible-build-tools.md&#34;&gt;https://github.com/apple/swift-evolution/blob/main/proposals/0303-swiftpm-extensible-build-tools.md&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/apple/swift-evolution/blob/main/proposals/0325-swiftpm-additional-plugin-apis.md&#34;&gt;https://github.com/apple/swift-evolution/blob/main/proposals/0325-swiftpm-additional-plugin-apis.md&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/apple/swift-evolution/blob/main/proposals/0332-swiftpm-command-plugins.md&#34;&gt;https://github.com/apple/swift-evolution/blob/main/proposals/0332-swiftpm-command-plugins.md&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/apple/swift-evolution/blob/main/proposals/0356-swift-snippets.md&#34;&gt;https://github.com/apple/swift-evolution/blob/main/proposals/0356-swift-snippets.md&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/apple/swift-package-manager/blob/main/Documentation/Plugins.md&#34;&gt;https://github.com/apple/swift-package-manager/blob/main/Documentation/Plugins.md&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;WWDC 2023 &lt;a href=&#34;https://developer.apple.com/videos/play/wwdc2023/10171/&#34;&gt;Meet Swift OpenAPI Generator&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;repos-with-interesting-plugins&#34;&gt;Repos with Interesting Plugins&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Example bringing in linting from &lt;code&gt;MessageKit&lt;/code&gt; &lt;a href=&#34;https://github.com/MessageKit/MessageKit/tree/3fab2f2d7f04b0f7ec19e2bfab0f614fef884ff8/Plugins&#34;&gt;https://github.com/MessageKit/MessageKit/tree/3fab2f2d7f04b0f7ec19e2bfab0f614fef884ff8/Plugins&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/SwiftGen/SwiftGenPlugin&#34;&gt;https://github.com/SwiftGen/SwiftGenPlugin&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/realm/SwiftLint/tree/main/Plugins/SwiftLintPlugin&#34;&gt;https://github.com/realm/SwiftLint/tree/main/Plugins/SwiftLintPlugin&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/apple/swift-docc-plugin&#34;&gt;https://github.com/apple/swift-docc-plugin&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/apple/swift-openapi-generator&#34;&gt;https://github.com/apple/swift-openapi-generator&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/lighter-swift&#34;&gt;https://github.com/lighter-swift&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;command-plugins&#34;&gt;Command Plugins&lt;/h2&gt;
&lt;p&gt;The first plugin I wrote was a command plugin. For &lt;a href=&#34;https://adventofcode.com/2023&#34;&gt;Advent of Code&lt;/a&gt; I wrote a CLI to generate boiler plate code each day. I wanted to see if I could reproduce that behavior with a plugin. I&amp;rsquo;ll write more about that later.&lt;/p&gt;
&lt;p&gt;As part of my trouble shooting process I wrote a plugin that would just write information about the plugin and the package to a file so I could figure out what all the variables were doing.&lt;/p&gt;
&lt;p&gt;I created a &lt;a href=&#34;https://github.com/carlynorama/PluginExplorer&#34;&gt;separate project&lt;/a&gt; to house this utility plugin so I could delete it from the original project. That project has become my plugin tester project and no longer contains just the code below. While still usable by other packages, the repo in its current state is not for use in projects. The code below can work in either.&lt;/p&gt;
&lt;h3 id=&#34;getting-started&#34;&gt;Getting Started&lt;/h3&gt;
&lt;p&gt;These are the general steps one can follow to make a command plugin. It can be imported into another package or project as a dependency and the plugin will be available to that package or project.&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;# handy thing to have done if you do this by hand a lot. 
git config --global alias.start-repo &amp;#39;!git init . &amp;amp;&amp;amp; git add . &amp;amp;&amp;amp; git commit --allow-empty -m &amp;#34;Initialize repository&amp;#34;&amp;#39;
&lt;/code&gt;&lt;/pre&gt;&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;mkdir $MYPLUGINNAME
cd $MYPLUGINNAME
swift package init --type command-plugin
touch README.md
# git start-repo if available (see above) 
git init .
git add .
git commit -m &amp;#34;Initialize repository&amp;#34;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This will create a directory structure that looks like&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-txt&#34; data-lang=&#34;txt&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;└── $MYPLUGINNAME
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    └── Plugins
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    │   └── $MYPLUGINNAME.swift
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    └── Package.swift
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    └── .git
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    └── .gitignore
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This is fine if it will only hold the one plug in, but you may prefer&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-txt&#34; data-lang=&#34;txt&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;└── $MYPLUGINNAME
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    └── Plugins
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    │   └── $MYPLUGINNAME
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    |       └── plugin.swift
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    └── Package.swift
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    └── .git
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    └── .gitignore
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;the-default-packageswift&#34;&gt;The Default Package.swift&lt;/h3&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// swift-tools-version: 5.9&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// The swift-tools-version declares the minimum version of Swift required to build this package.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;PackageDescription&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;package&lt;/span&gt; = Package(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    name: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;$MYPLUGINNAME&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    products: [
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// Products can be used to vend plugins, making them visible to other packages.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        .plugin(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            name: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;$MYPLUGINNAME&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            targets: [&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;$MYPLUGINNAME&amp;#34;&lt;/span&gt;]),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    ],
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    targets: [
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// Targets are the basic building blocks of a package, defining a module or a test suite.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// Targets can depend on other targets in this package and products from dependencies.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//NOTE FROM ME: You will not have to update the path parameter if you move the &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//plugin code into Plugin/\(name)/plugin.swift&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        .plugin(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            name: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;$MYPLUGINNAME&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            capability: .command(intent: .custom(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                verb: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;$MYPLUGINNAME&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                description: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;prints hello world&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            ))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        ),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    ]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;the-default-pluginswift&#34;&gt;The Default plugin.swift&lt;/h3&gt;
&lt;p&gt;The contents of $MYPLUGINNAME.swift/plugin.swift will have a &lt;code&gt;func performCommand&lt;/code&gt; for packages and a &lt;code&gt;func performCommand&lt;/code&gt; for Xcode projects that are not packages.&lt;/p&gt;
&lt;p&gt;Here&amp;rsquo;s what it looks like with a couple of comments from me.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;PackagePlugin&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//NOTE THE MAIN, plugins are stand alone scripts that require an entry point. &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//If your code doesn&amp;#39;t run check to make sure you have this. &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;@main &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//&amp;lt;== &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;$&lt;/span&gt;MYPLUGINNAME: CommandPlugin {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// Entry point for command plugins applied to Swift Packages.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;performCommand&lt;/span&gt;(context: PluginContext, arguments: [&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;]) async &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Hello, World!&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#if&lt;/span&gt; &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;canImport&lt;/span&gt;(&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;XcodeProjectPlugin&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;XcodeProjectPlugin&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;extension&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;MyCommandPlugin&lt;/span&gt;: XcodeCommandPlugin {   &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//&amp;lt;====== NOT THE SAME NAME WILL HAVE TO FIX&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// Entry point for command plugins applied to Xcode projects.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;performCommand&lt;/span&gt;(context: XcodePluginContext, arguments: [&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;]) &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Hello, World!&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#endif&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;(&lt;a href=&#34;https://github.com/apple/swift-package-manager/pull/7277&#34;&gt;name fix PR&lt;/a&gt;)&lt;/p&gt;
&lt;p&gt;It has both because some of the variables in the &lt;code&gt;XcodePluginContext&lt;/code&gt; are different than the &lt;code&gt;PluginContext&lt;/code&gt;. For example:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//CommandPlugin&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;location&lt;/span&gt; = context.package.directory.appending([fileName])
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//XcodeCommandPlugin&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;location&lt;/span&gt; = context.xcodeProject.directory.appending([fileName])
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;See&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://forums.swift.org/t/using-build-tool-plugins-with-xcproj/56064/9&#34;&gt;https://forums.swift.org/t/using-build-tool-plugins-with-xcproj/56064/9&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/apple/swift-package-manager/blob/main/Documentation/Plugins.md#xcode-extensions-to-the-packageplugin-api&#34;&gt;https://github.com/apple/swift-package-manager/blob/main/Documentation/Plugins.md#xcode-extensions-to-the-packageplugin-api&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;One thing to keep in mind, if your command plugin generates files in a target&amp;rsquo;s source directory the behavior will be different for a package vs an &lt;code&gt;App.xcodeproj&lt;/code&gt;. The plugin for Xcode projects may successfully generate files in the right directory but the project will not know about them until they are added to the project by hand. (File &amp;gt; Add Files) There may be a way but &lt;a href=&#34;https://developer.apple.com/forums/thread/744870&#34;&gt;I don&amp;rsquo;t know it&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&#34;my-plugin-code&#34;&gt;My Plugin Code&lt;/h3&gt;
&lt;p&gt;Here is my plugin for spitting out values from the &lt;code&gt;context&lt;/code&gt; parameter and writing them to file. There is duplication between the two that I may go back and tidy up, but in the short term it wasn&amp;rsquo;t worth it to me.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//  TellMeAboutYourself/plugin.swift&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//  Created by Carlyn Maw on 1/14/24.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//Print statements can be found in build log in Xcode in &amp;#34;Package&amp;#34; section.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;PackagePlugin&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;Foundation&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;@main
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;TellMeAboutYourself&lt;/span&gt;: CommandPlugin {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;performCommand&lt;/span&gt;(context: PackagePlugin.PluginContext,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                        arguments: [&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;]) async &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;fileName&lt;/span&gt; = &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;WhatThePluginSees&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;+&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;.txt&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;message&lt;/span&gt; = &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Arguments Info&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        message.append(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\n&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;arguments:&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;arguments&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;argExtractor&lt;/span&gt; = ArgumentExtractor(arguments)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        message.append(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\n&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;argument extractor:&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;argExtractor&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;targetNames&lt;/span&gt; = argExtractor.extractOption(named: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;target&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        message.append(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\n&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;extracted names:&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;targetNames&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        message.append(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\n\n&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;Context Info&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        message.append(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\n&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;workDirectory: &lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;context.pluginWorkDirectory&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        message.append(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\n\n&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;Package Info&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        message.append(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\n&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;origin: &lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;context.package.origin&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        message.append(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\n&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;directory: &lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;context.package.directory&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        message.append(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\n&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;products:&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;context.package.products.&lt;span style=&#34;color:#91d7e3&#34;&gt;map&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;(&lt;/span&gt;{&lt;span style=&#34;color:#f4dbd6&#34;&gt;$0&lt;/span&gt;.name}&lt;span style=&#34;color:#a6da95&#34;&gt;))&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        message.append(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\n&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;all targets:&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;context.package.targets.&lt;span style=&#34;color:#91d7e3&#34;&gt;map&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;(&lt;/span&gt;{&lt;span style=&#34;color:#f4dbd6&#34;&gt;$0&lt;/span&gt;.name}&lt;span style=&#34;color:#a6da95&#34;&gt;))&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//Cannot find &amp;#39;PluginTarget&amp;#39; in scope&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//SwiftSourceModuleTarget.self does work.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//let specialTargets = context.package.targets(ofType: PluginTarget.self)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//Nope. No plugins in here.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;targets&lt;/span&gt; = context.package.targets
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//FWIW not even if you asked for them explicitly.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//let targets = try context.package.targets(named: targetNames)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;targetDirectories&lt;/span&gt; = targets.&lt;span style=&#34;color:#91d7e3&#34;&gt;map&lt;/span&gt;({&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\n&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;directory for &lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;$0&lt;/span&gt;.name&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;: &lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;$0&lt;/span&gt;.directory&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;})
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;for&lt;/span&gt; dir &lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt; targetDirectories {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            message.append(dir)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        message.append(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\n\n&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;Swift Source Files&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;packageDir&lt;/span&gt; = context.package.directory.lastComponent
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;for&lt;/span&gt; target &lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt; targets {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//let targetDir = target.directory.lastComponent&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;sourceList&lt;/span&gt; = target.sourceModule?.sourceFiles(withSuffix: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;.swift&amp;#34;&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                sourceList.forEach({ sourceFile &lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;fullPath&lt;/span&gt; = sourceFile.path.string
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;range&lt;/span&gt; = fullPath.firstRange(of: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;packageDir&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//if used .name instead of .directory.lastComponent&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//would need this redundancy for sure. probably overkill here.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;pathStart&lt;/span&gt; = range?.lowerBound ?? fullPath.startIndex
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;relativePath&lt;/span&gt; = fullPath.&lt;span style=&#34;color:#91d7e3&#34;&gt;suffix&lt;/span&gt;(from: pathStart)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    message.append(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\n&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;relativePath&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\t&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;type:&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;sourceFile.type&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                })
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        message.append(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\n\n\n&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;--------------------------------------------------------------------&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        message.append(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\n&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;DUMPS&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\n&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//message.append(&amp;#34;\(context)&amp;#34;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//message.append(&amp;#34;\nsourceModules: \(context.package.sourceModules)&amp;#34;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//message.append(&amp;#34;\nproducts:\(context.package.products)&amp;#34;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//message.append(&amp;#34;\ntargets:\(context.package.targets)&amp;#34;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//let sources = targets.map({ $0.sourceModule?.sourceFiles })&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//message.append(&amp;#34;\n\nsourceFiles:\(sources)&amp;#34;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;location&lt;/span&gt; = context.package.directory.appending([fileName])
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; writeToFile(location: location, content: message)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;writeToFile&lt;/span&gt;(location:Path, content:some StringProtocol) &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; content.write(toFile: location.string, atomically: &lt;span style=&#34;color:#f5a97f&#34;&gt;true&lt;/span&gt;, encoding: .utf8)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#if&lt;/span&gt; &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;canImport&lt;/span&gt;(&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;XcodeProjectPlugin&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;XcodeProjectPlugin&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;extension&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;TellMeAboutYourself&lt;/span&gt;: XcodeCommandPlugin {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;performCommand&lt;/span&gt;(context: XcodeProjectPlugin.XcodePluginContext, arguments: [&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;]) &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;fileName&lt;/span&gt; = &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;WhatThePluginSees&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;+&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;.txt&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;message&lt;/span&gt; = &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Arguments Info&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        message.append(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\n&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;arguments:&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;arguments&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;argExtractor&lt;/span&gt; = ArgumentExtractor(arguments)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        message.append(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\n&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;argument extractor:&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;argExtractor&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;targetNames&lt;/span&gt; = argExtractor.extractOption(named: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;target&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        message.append(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\n&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;extracted names:&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;targetNames&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        message.append(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\n\n&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;Context Info&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        message.append(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\n&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;workDirectory: &lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;context.pluginWorkDirectory&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        message.append(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\n\n&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;Package Info&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        message.append(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\n&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;Not available for an xcodeProject&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        message.append(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\n\n&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;XodeProject Info&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;project&lt;/span&gt; = context.xcodeProject
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        message.append(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\n&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;directory: &lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;context.xcodeProject.directory&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        message.append(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\n&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;filePaths: &lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;context.xcodeProject.filePaths&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        message.append(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\n&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;all targets:&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;context.xcodeProject.targets.&lt;span style=&#34;color:#91d7e3&#34;&gt;map&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;(&lt;/span&gt;{&lt;span style=&#34;color:#f4dbd6&#34;&gt;$0&lt;/span&gt;.displayName}&lt;span style=&#34;color:#a6da95&#34;&gt;))&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;targets&lt;/span&gt; = context.xcodeProject.targets
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;targetDirectories&lt;/span&gt; = targets.&lt;span style=&#34;color:#91d7e3&#34;&gt;map&lt;/span&gt;({&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\n&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;$0&lt;/span&gt;.displayName&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt; of type &lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;(&lt;/span&gt;describing: &lt;span style=&#34;color:#f4dbd6&#34;&gt;$0&lt;/span&gt;.product&lt;span style=&#34;color:#a6da95&#34;&gt;))&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;})
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;for&lt;/span&gt; dir &lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt; targetDirectories {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            message.append(dir)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        message.append(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\n\n&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;Swift Source Files&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;packageDir&lt;/span&gt; = context.xcodeProject.directory.lastComponent
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;for&lt;/span&gt; target &lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt; targets {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//let targetDir = target.directory.lastComponent&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;               &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;sourceList&lt;/span&gt; = target.inputFiles.&lt;span style=&#34;color:#91d7e3&#34;&gt;filter&lt;/span&gt;({&lt;span style=&#34;color:#f4dbd6&#34;&gt;$0&lt;/span&gt;.type == .source})
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                sourceList.forEach({ sourceFile &lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;fullPath&lt;/span&gt; = sourceFile.path.string
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;range&lt;/span&gt; = fullPath.firstRange(of: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;packageDir&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//if used .name instead of .directory.lastComponent&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//would need this redundancy for sure. probably overkill here.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;pathStart&lt;/span&gt; = range?.lowerBound ?? fullPath.startIndex
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;relativePath&lt;/span&gt; = fullPath.&lt;span style=&#34;color:#91d7e3&#34;&gt;suffix&lt;/span&gt;(from: pathStart)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    message.append(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\n&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;relativePath&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\t&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;type:&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;sourceFile.type&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                })
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        message.append(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\n\n\n&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;--------------------------------------------------------------------&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        message.append(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\n&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;DUMPS&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\n&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//message.append(&amp;#34;\(context)&amp;#34;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;location&lt;/span&gt; = context.xcodeProject.directory.appending([fileName])
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; writeToFile(location: location, content: message)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#endif&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;update-packageswift&#34;&gt;Update package.swift&lt;/h3&gt;
&lt;p&gt;Add the request for permission to the package manifest.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;.plugin(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    name: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;TellMeAboutYourself&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    capability: .command(intent: .custom(verb: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;about&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                                  description: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;See info about the package&amp;#34;&lt;/span&gt;),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    permissions: [.writeToPackageDirectory(reason: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;This plugin creates a file with information about the plugin and the package it&amp;#39;s running on.&amp;#34;&lt;/span&gt;)]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                )
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;running-the-plugin&#34;&gt;Running the plugin.&lt;/h3&gt;
&lt;p&gt;The plugin should be available when you right click the package that depends on it or contains it in Xcode&amp;rsquo;s file list. If not, try updating the package or closing and reopening the project.&lt;/p&gt;
&lt;p&gt;In the command line&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;cd $YOUR_PACKAGE
# See the plugin available to that package
swift package plugin --list
# run the one you want
swift package $PLUGIN_VERB
# run the one you want silencing (with agreement) the write permissions request
swift package --allow-writing-to-package-directory $PLUGIN_VERB
&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=&#34;running-an-existing-tool-instead&#34;&gt;Running an existing tool instead.&lt;/h3&gt;
&lt;p&gt;One thing I found unintuitive is that although plugins are listed as targets in the the target section, they are &lt;a href=&#34;https://forums.swift.org/t/package-command-plugins-cant-see-plugin-targets/69439&#34;&gt;not listed as targets in the plugin context&lt;/a&gt;. This means that for long involved plugins the better approach would be to put as much as possible into an external tool. As a bonus, this also allows command plugins to &lt;a href=&#34;https://forums.swift.org/t/difficulty-sharing-code-between-swift-package-manager-plugins/61690/3&#34;&gt;share code with build plugins&lt;/a&gt;.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/apple/swift-package-manager/blob/4b7ee3e328dc8e7bec33d4d5d401d37abead6e41/Sources/PackageModel/Target/PluginTarget.swift#L13&#34;&gt;https://github.com/apple/swift-package-manager/blob/4b7ee3e328dc8e7bec33d4d5d401d37abead6e41/Sources/PackageModel/Target/PluginTarget.swift#L13&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://forums.swift.org/t/package-command-plugins-cant-see-plugin-targets/69439/1&#34;&gt;https://forums.swift.org/t/package-command-plugins-cant-see-plugin-targets/69439/1&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;An example of a command plugin running a tool that it shares with a build plugin is what &lt;a href=&#34;https://github.com/MessageKit/MessageKit/tree/3fab2f2d7f04b0f7ec19e2bfab0f614fef884ff8/Plugins&#34;&gt;MessageKit does with SwiftLint&lt;/a&gt;. They define their tool with &lt;code&gt;let swiftLintTool = try context.tool(named: &amp;quot;swiftlint&amp;quot;)&lt;/code&gt;, where the binary for &lt;code&gt;swiftlint&lt;/code&gt; is defined in the package.  Plugins can depend on any binary that the shell spawned by build tool will see, including ones in &lt;code&gt;/bin/&lt;/code&gt;. Using a tool not defined in the package means the developer using the plugin may not have it in their environment. Look for the error &amp;ldquo;&lt;code&gt;Plugin does not have access to a tool named ‘$WHATYOUTRIED’&lt;/code&gt;&amp;rdquo;.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;Foundation&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;PackagePlugin&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// &lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;MARK:&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt; - SwiftLintCommandPlugin&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;@main
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;SwiftLintCommandPlugin&lt;/span&gt;: CommandPlugin {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;performCommand&lt;/span&gt;(context: PackagePlugin.PluginContext, arguments &lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt;: [&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;]) async &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;swiftLintTool&lt;/span&gt; = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; context.tool(named: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;swiftlint&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;swiftLintPath&lt;/span&gt; = URL(fileURLWithPath: swiftLintTool.path.string)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;swiftLintArgs&lt;/span&gt; = [
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;lint&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;--path&amp;#34;&lt;/span&gt;, context.package.directory.string,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;--config&amp;#34;&lt;/span&gt;, context.package.directory.string &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;+&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;/.swiftlint.yml&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;--strict&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    ]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;task&lt;/span&gt; = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;Process&lt;/span&gt;.run(swiftLintPath, arguments: swiftLintArgs)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    task.waitUntilExit()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; task.terminationStatus == &lt;span style=&#34;color:#f5a97f&#34;&gt;0&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;||&lt;/span&gt; task.terminationStatus == &lt;span style=&#34;color:#f5a97f&#34;&gt;2&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// no-op&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    } &lt;span style=&#34;color:#c6a0f6&#34;&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#c6a0f6&#34;&gt;throw&lt;/span&gt; CommandError.unknownError(exitCode: task.terminationStatus)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// &lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;MARK:&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt; - CommandError&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;enum&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;CommandError&lt;/span&gt;: Error {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#c6a0f6&#34;&gt;case&lt;/span&gt; unknownError(exitCode: &lt;span style=&#34;color:#91d7e3&#34;&gt;Int32&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;summary&#34;&gt;Summary&lt;/h3&gt;
&lt;p&gt;Command plugins let you run tools on demand in your project through a handy XCode interface or in the command line. They can lookup information about your project without it being hand coded every time, which gives them a leg up over a generic CLI in which you might have to hand code (and get wrong) a file path.&lt;/p&gt;
&lt;p&gt;The examples shown tend to be generating resource files or applying formatting to existing code. It seems like the &amp;ldquo;Swifty Way&amp;rdquo; to generate actual source code is to use a build plugin or a prebuild plugin which will put that code directly into the build folder instead. This keeps you from &amp;ldquo;cluttering your source folder&amp;rdquo;. So that&amp;rsquo;s what we&amp;rsquo;ll do next!&lt;/p&gt;
&lt;p&gt;See more in &lt;a href=&#34;https://whynotestflight.com/excuses/what-if-instead-of-a-cli-plugins-part-2-start-a-build-plugin/&#34;&gt;Part 2, Build Plugin Start&lt;/a&gt;&lt;/p&gt;
</description>
    </item>
    
    
    
    <item>
      <title>Can I open a serial port with Swift? Part II</title>
      <link>https://whynotestflight.com/excuses/can-i-open-a-serial-port-with-swift-part-ii/</link>
      <pubDate>Tue, 29 Aug 2023 00:00:00 +0000</pubDate>
      
      <guid>https://whynotestflight.com/excuses/can-i-open-a-serial-port-with-swift-part-ii/</guid>
      <description>&lt;p&gt;Another brain dump, building on the &lt;a href=&#34;https://whynotestflight.com/excuses/can-i-open-a-serial-port-with-swift-part-i/&#34;&gt;last post&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;SwiftSerialToArduino_20230829.zip&#34;&gt;Download 3 project code zip (741kb)&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Relevant Repos:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/carlynorama/swiftserialport&#34;&gt;https://github.com/carlynorama/swiftserialport&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/carlynorama/SerialSession&#34;&gt;https://github.com/carlynorama/SerialSession&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/carlynorama/SerialSessionUI&#34;&gt;https://github.com/carlynorama/SerialSessionUI&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Shocking no one, I did not focus on the higher level API and did in fact write my own &lt;a href=&#34;https://github.com/carlynorama/swiftserialport&#34;&gt;SwiftSerialPort&lt;/a&gt; library.&lt;/p&gt;
&lt;p&gt;Lucky for me, I can pretty easily get my hands on the very same &lt;a href=&#34;https://mastodon.social/@todbot/&#34;&gt;@todbot&lt;/a&gt; (&amp;lt;3) whose &lt;a href=&#34;https://github.com/todbot/arduino-serial&#34;&gt;arduino-serial&lt;/a&gt; library was referenced in so many of the links provided by &lt;a href=&#34;https://yeokhengmeng.com&#34;&gt;yeokm1&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://github.com/yeokm1/SwiftSerial&#34;&gt;SwiftSerial&lt;/a&gt; served very well as a place to start. I&amp;rsquo;m just targeting such a different application that a fork wasn&amp;rsquo;t allowing me to do the reorg I wanted.&lt;/p&gt;
&lt;p&gt;Some of the differences in &lt;code&gt;SwiftSerialPort&lt;/code&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A &lt;code&gt;SerialPort&lt;/code&gt; is a class instead of a struct. It must be able to create a file descriptor in order to &lt;code&gt;init&lt;/code&gt;. It closes on &lt;code&gt;deinit&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;I pulled much of the C into it&amp;rsquo;s own section of the Package. I can then import it (and not Foundation) into the Swift as needed.&lt;/li&gt;
&lt;li&gt;I made a CLI target for testing things as I go. It&amp;rsquo;s called &lt;code&gt;cereal&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Different enums for different types of Errors&lt;/li&gt;
&lt;li&gt;I rely much more on the &lt;code&gt;termios&lt;/code&gt; struct&amp;rsquo;s default settings. I&amp;rsquo;m not really going to do much that doesn&amp;rsquo;t have an &lt;a href=&#34;https://en.wikipedia.org/wiki/8-N-1&#34;&gt;8N1&lt;/a&gt; setting, for example.  It works. I&amp;rsquo;m not going to poke at it.&lt;/li&gt;
&lt;li&gt;On a related note, I didn&amp;rsquo;t enjoy using an enum for the baud rates. I can now just type what I want and have a C function validate it. That was a &lt;a href=&#34;https://github.com/todbot/arduino-serial/blob/e5958dc3bfd44a303456ff22da53974424da646d/arduino-serial-lib.c#L47&#34;&gt;todism&lt;/a&gt;. (see &lt;a href=&#34;https://github.com/carlynorama/SwiftSerialPort/blob/5ee18d946b8eacd564fb324815e359679968ed09/Sources/SerialC/port.c#L61&#34;&gt;validate_baudrate&lt;/a&gt; as the derivative)&lt;/li&gt;
&lt;li&gt;The write function takes a generic input parameter, while also taking advantage of the 5.7 introduced unsafe closure syntax &lt;code&gt;withUnsafeByes {}&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;write&lt;/span&gt;&amp;lt;T&amp;gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; outBytes:T) &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; -&amp;gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;Int&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; withUnsafeBytes(of: outBytes) { message &lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;r&lt;/span&gt; = write_to_port(fileDescriptor, message.baseAddress, message.&lt;span style=&#34;color:#91d7e3&#34;&gt;count&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; r == &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;-&lt;/span&gt;&lt;span style=&#34;color:#f5a97f&#34;&gt;1&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#c6a0f6&#34;&gt;throw&lt;/span&gt; SerialCommunicationError.couldNotWrite
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; r
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ul&gt;
&lt;li&gt;For my line reader I do a batch read of everything available and then parse it out in Swift. Much more efficient, but it still needs a little work on handling mid-line breaks.&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;readAvailableLines&lt;/span&gt;(maxSplits:&lt;span style=&#34;color:#91d7e3&#34;&gt;Int&lt;/span&gt; = &lt;span style=&#34;color:#f5a97f&#34;&gt;10000&lt;/span&gt;) &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; -&amp;gt; (lines:[&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;], remainder:&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;buffer&lt;/span&gt; = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; readAllAvailable()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        buffer.append(&lt;span style=&#34;color:#f5a97f&#34;&gt;0&lt;/span&gt;) &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//cString must be null terminated &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;dataAsString&lt;/span&gt; = &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;(cString: buffer)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;remainder&lt;/span&gt;:&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;lastNewLine&lt;/span&gt; =  dataAsString.lastIndex(&lt;span style=&#34;color:#c6a0f6&#34;&gt;where&lt;/span&gt;: { &lt;span style=&#34;color:#f4dbd6&#34;&gt;$0&lt;/span&gt;.isNewline }) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            remainder = &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;(dataAsString[lastNewLine...].trimmingPrefix(&lt;span style=&#34;color:#c6a0f6&#34;&gt;while&lt;/span&gt;: { &lt;span style=&#34;color:#f4dbd6&#34;&gt;$0&lt;/span&gt;.isNewline }))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            dataAsString.removeSubrange(lastNewLine...)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        } &lt;span style=&#34;color:#c6a0f6&#34;&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            remainder = &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;lines&lt;/span&gt; = dataAsString.&lt;span style=&#34;color:#91d7e3&#34;&gt;split&lt;/span&gt;(maxSplits: maxSplits, 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                                                 omittingEmptySubsequences: &lt;span style=&#34;color:#f5a97f&#34;&gt;true&lt;/span&gt;, 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                                                 whereSeparator: { &lt;span style=&#34;color:#f4dbd6&#34;&gt;$0&lt;/span&gt;.isNewline })
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                                          .&lt;span style=&#34;color:#91d7e3&#34;&gt;map&lt;/span&gt; { &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;(&lt;span style=&#34;color:#f4dbd6&#34;&gt;$0&lt;/span&gt;) }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(lines)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; (lines, remainder)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ul&gt;
&lt;li&gt;I did write and async function that can accommodate a blocking read. I also made it possible to specify  read timeout/escape early parameters by setting &lt;a href=&#34;http://unixwiz.net/techtips/termios-vmin-vtime.html&#34;&gt;VTIME and VMIN&lt;/a&gt; for the port.&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//updates port configuration to time out of waiting, if desired. &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//Adding a byte min means code will not return until it has AT LEAST that many bytes.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; serialPort.setReadEscapes(wait:&lt;span style=&#34;color:#f5a97f&#34;&gt;30&lt;/span&gt;, minNumberOfBytes:&lt;span style=&#34;color:#f5a97f&#34;&gt;0&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//make the async call.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;async &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;incomingMessage3&lt;/span&gt; = serialPort.awaitBytes(&lt;span style=&#34;color:#91d7e3&#34;&gt;count&lt;/span&gt;: &lt;span style=&#34;color:#f5a97f&#34;&gt;20&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//proof code can go do other things.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;some other activities...&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//depending on whats on the Ardunio and/or what I put in setReadEscapes&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//could be almost instant, could be never. &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;awaited: &lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;await incomingMessage3&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//wait is in tenths of seconds&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//minNumberOfBytes should be lower than the bytes the read is requesting.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//see http://unixwiz.net/techtips/termios-vmin-vtime.html&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;setReadEscapes&lt;/span&gt;(wait vtime:&lt;span style=&#34;color:#91d7e3&#34;&gt;UInt8&lt;/span&gt;, minNumberOfBytes vmin:&lt;span style=&#34;color:#91d7e3&#34;&gt;UInt8&lt;/span&gt;) &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;errors&lt;/span&gt; = set_early_fail_behavior(fileDescriptor, vtime, vmin) 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; errors &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;lt;&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;0&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;throw&lt;/span&gt; SerialSettingsError.settingNotUpdated
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-C&#34; data-lang=&#34;C&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//assumes the following style opening.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//    fd = open(&amp;#34;/dev/ttyS0&amp;#34;, O_RDWR | O_NOCTTY | O_NDELAY);
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//    fcntl(fd, F_SETFL, 0);
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;int&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;set_early_fail_behavior&lt;/span&gt;(&lt;span style=&#34;color:#c6a0f6&#34;&gt;const&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;int&lt;/span&gt; file_descriptor, &lt;span style=&#34;color:#c6a0f6&#34;&gt;const&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;cc_t&lt;/span&gt; new_vtime, &lt;span style=&#34;color:#c6a0f6&#34;&gt;const&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;cc_t&lt;/span&gt; new_vmin) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;/* get the current options */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;int&lt;/span&gt; r;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;struct&lt;/span&gt; termios settings;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#8aadf4&#34;&gt;tcgetattr&lt;/span&gt;(file_descriptor, &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;amp;&lt;/span&gt;settings);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; (r &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;lt;&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;0&lt;/span&gt;) { 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#8aadf4&#34;&gt;perror&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;update_baudrate: couldn&amp;#39;t get current settings&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;-&lt;/span&gt;&lt;span style=&#34;color:#f5a97f&#34;&gt;1&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    settings.c_cc[VTIME] &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; new_vtime;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//10;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;    settings.c_cc[VMIN]  &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; new_vmin; &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//0
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;/* set the options */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#8aadf4&#34;&gt;tcsetattr&lt;/span&gt;(file_descriptor, TCSANOW, &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;amp;&lt;/span&gt;settings);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; (r &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;lt;&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;0&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#8aadf4&#34;&gt;perror&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;update_baudrate: couldn&amp;#39;t set VTIME and VMIN&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;-&lt;/span&gt;&lt;span style=&#34;color:#f5a97f&#34;&gt;2&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;0&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;awaitBytes&lt;/span&gt;(&lt;span style=&#34;color:#91d7e3&#34;&gt;count&lt;/span&gt;:&lt;span style=&#34;color:#91d7e3&#34;&gt;Int&lt;/span&gt;) async -&amp;gt; Result&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;lt;&lt;/span&gt;[&lt;span style=&#34;color:#91d7e3&#34;&gt;UInt8&lt;/span&gt;], Error&amp;gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;dataBuffer&lt;/span&gt; = &lt;span style=&#34;color:#91d7e3&#34;&gt;Array&lt;/span&gt;&amp;lt;&lt;span style=&#34;color:#91d7e3&#34;&gt;UInt8&lt;/span&gt;&amp;gt;(repeating: &lt;span style=&#34;color:#f5a97f&#34;&gt;0&lt;/span&gt;, &lt;span style=&#34;color:#91d7e3&#34;&gt;count&lt;/span&gt;: &lt;span style=&#34;color:#91d7e3&#34;&gt;count&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;bytesReceived&lt;/span&gt; = dataBuffer.withUnsafeMutableBufferPointer { bufferPointer &lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; default_read_from_port(fileDescriptor, bufferPointer.baseAddress, &lt;span style=&#34;color:#91d7e3&#34;&gt;count&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; bytesReceived == &lt;span style=&#34;color:#f5a97f&#34;&gt;0&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//Depends on port settings if this is possible&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; .failure(SerialCommunicationError.noBytesReceived)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        } &lt;span style=&#34;color:#c6a0f6&#34;&gt;else&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; bytesReceived &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;lt;&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;0&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; .failure(SerialCommunicationError.couldNotRead)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; .success(&lt;span style=&#34;color:#91d7e3&#34;&gt;Array&lt;/span&gt;(dataBuffer.&lt;span style=&#34;color:#c6a0f6&#34;&gt;prefix&lt;/span&gt;(bytesReceived)))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-C&#34; data-lang=&#34;C&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//Uses port settings. 
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;size_t&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;default_read_from_port&lt;/span&gt;(&lt;span style=&#34;color:#c6a0f6&#34;&gt;const&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;int&lt;/span&gt; file_descriptor, &lt;span style=&#34;color:#ed8796&#34;&gt;void&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;*&lt;/span&gt; buffer, &lt;span style=&#34;color:#c6a0f6&#34;&gt;const&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;size_t&lt;/span&gt; count) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;int&lt;/span&gt; result &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;read&lt;/span&gt;(file_descriptor, buffer, count);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; result;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;what-else-is-new&#34;&gt;What else is new&lt;/h2&gt;
&lt;p&gt;The two original repos got a face lift, swapping in SwiftSerialPort library.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/carlynorama/SerialSession&#34;&gt;https://github.com/carlynorama/SerialSession&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/carlynorama/SerialSessionUI&#34;&gt;https://github.com/carlynorama/SerialSessionUI&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;serialsessionui-the-macosswiftui-project-has-3-views-now&#34;&gt;SerialSessionUI, the MacOS/SwiftUI project, has 3 views now&lt;/h3&gt;
&lt;table&gt;
  &lt;thead&gt;
      &lt;tr&gt;
          &lt;th&gt;View A&lt;/th&gt;
          &lt;th&gt;View B&lt;/th&gt;
          &lt;th&gt;View C&lt;/th&gt;
      &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;img src=&#34;A_writeview.png&#34; alt=&#34;screen shot&#34;&gt;&lt;/td&gt;
          &lt;td&gt;&lt;img src=&#34;B_bytedumpview.png&#34; alt=&#34;screen shot&#34;&gt;&lt;/td&gt;
          &lt;td&gt;&lt;img src=&#34;C_linesview.png&#34; alt=&#34;screen shot&#34;&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;A write view with a slider&lt;/td&gt;
          &lt;td&gt;A read view that batch dumps bytes into the screen after casting the data as a String (if possible).&lt;/td&gt;
          &lt;td&gt;A view that breaks transmitted ASCII text (new lines separated) into an array of Strings.&lt;/td&gt;
      &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;SwiftUI&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;SerialSession&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//Assumes code on board is ForWriteView.ino&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;WriteView&lt;/span&gt;: View {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    @EnvironmentObject &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;serialWriter&lt;/span&gt;:SerialSession
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    @State &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;brightness&lt;/span&gt;:&lt;span style=&#34;color:#91d7e3&#34;&gt;Double&lt;/span&gt; = &lt;span style=&#34;color:#f5a97f&#34;&gt;0.5&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    @State &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;toTransmit&lt;/span&gt;:&lt;span style=&#34;color:#91d7e3&#34;&gt;UInt8&lt;/span&gt; = &lt;span style=&#34;color:#91d7e3&#34;&gt;UInt8&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;0.5&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;*&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;255&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    @State &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;sent&lt;/span&gt; = &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;–&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;body&lt;/span&gt;: some View {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        VStack(alignment: .leading) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            Text(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;slider:&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;brightness&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;, toSend:&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;toTransmit&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt; (&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;sent&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;)&amp;#34;&lt;/span&gt;).monospaced()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            Slider(value: &lt;span style=&#34;color:#ed8796&#34;&gt;$&lt;/span&gt;brightness) { editing &lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;!&lt;/span&gt;editing {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    toTransmit = &lt;span style=&#34;color:#91d7e3&#34;&gt;UInt8&lt;/span&gt;(brightness &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;*&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;255&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;result&lt;/span&gt; = serialWriter.send(toTransmit)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    &lt;span style=&#34;color:#c6a0f6&#34;&gt;switch&lt;/span&gt; result {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    &lt;span style=&#34;color:#c6a0f6&#34;&gt;case&lt;/span&gt; .success:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                        sent = &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;√&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    &lt;span style=&#34;color:#c6a0f6&#34;&gt;case&lt;/span&gt; .failure(&lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;error&lt;/span&gt;):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                        sent = &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;X&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                        &lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(error)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        .padding()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;SwiftUI&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;SerialSession&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;LineBatchView&lt;/span&gt;: View {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    @EnvironmentObject &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;serialReader&lt;/span&gt;:SerialSession
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    @State &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;availableLines&lt;/span&gt;:[&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;] = &lt;span style=&#34;color:#91d7e3&#34;&gt;Array&lt;/span&gt;(repeating: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;No data yet&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#91d7e3&#34;&gt;count&lt;/span&gt;: &lt;span style=&#34;color:#f5a97f&#34;&gt;1&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    @State &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;remainder&lt;/span&gt; = &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;body&lt;/span&gt;: some View {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        VStack {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            Button(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Read&amp;#34;&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                updateLines()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            ScrollView {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                ForEach(&lt;span style=&#34;color:#91d7e3&#34;&gt;Array&lt;/span&gt;(availableLines.enumerated()), id: &lt;span style=&#34;color:#ed8796&#34;&gt;\&lt;/span&gt;.offset) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    Text(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;$0&lt;/span&gt;.offset&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;: &lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;$0&lt;/span&gt;.element&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;).monospaced()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;updateLines&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//let result = serialReader.readLine()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;result&lt;/span&gt; = serialReader.readLines()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;switch&lt;/span&gt; result {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;case&lt;/span&gt; .success(&lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;data&lt;/span&gt;):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;dataIterator&lt;/span&gt; = data.lines.makeIterator()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;while&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;line&lt;/span&gt; = dataIterator.next() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(line, terminator: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;, &amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//Maybe?&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            availableLines = data.lines
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            availableLines[&lt;span style=&#34;color:#f5a97f&#34;&gt;0&lt;/span&gt;] = remainder &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;+&lt;/span&gt; availableLines[&lt;span style=&#34;color:#f5a97f&#34;&gt;0&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            remainder = data.remainder
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;case&lt;/span&gt; .failure(&lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;error&lt;/span&gt;):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            availableLines = &lt;span style=&#34;color:#91d7e3&#34;&gt;Array&lt;/span&gt;(repeating: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;No data available&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#91d7e3&#34;&gt;count&lt;/span&gt;: &lt;span style=&#34;color:#f5a97f&#34;&gt;1&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            remainder = &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(error)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;SwiftUI&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;SerialSession&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//Assumes code on board is ForReadBytesView.ino&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;ReadAvailableBytesView&lt;/span&gt;: View {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    @EnvironmentObject &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;serialReader&lt;/span&gt;:SerialSession
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    @State &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;reading&lt;/span&gt;:&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt; = &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Press button to retrieve available data&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;body&lt;/span&gt;: some View {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        VStack {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            Text(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;reading&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            Button(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Read&amp;#34;&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                updateText()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        .padding()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;updateText&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//let result = serialReader.readLine()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;result&lt;/span&gt; = serialReader.readAvailable()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;switch&lt;/span&gt; result {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;case&lt;/span&gt; .success(&lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;message&lt;/span&gt;):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;dataIterator&lt;/span&gt; = message.makeIterator()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;while&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;animal&lt;/span&gt; = dataIterator.next() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(animal, terminator: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;, &amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            reading = &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;(data: message, encoding: .utf8) ?? &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;failure decoding.&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;case&lt;/span&gt; .failure(&lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;error&lt;/span&gt;):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            reading = &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;(no data available)&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(error)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The Arduino code for View A and View C were provided in the &lt;a href=&#34;(/excuses/can-i-open-a-serial-port-with-swift-part-i/)&#34;&gt;last post&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The code for View B:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-Cpp&#34; data-lang=&#34;Cpp&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;/*
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;Prints bytes that happen to be valid ascii characters to the serial 
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;port in a repeating loop. 
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;The circuit:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;  - None to speak of
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;  created 2023
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;  by Carlyn Maw
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;  
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;  This example code is in the public domain.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;*/&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;void&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;setup&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// initialize the serial communication:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;  Serial.begin(&lt;span style=&#34;color:#f5a97f&#34;&gt;9600&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;int&lt;/span&gt; thisByte &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;33&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;void&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;loop&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  Serial.write(thisByte);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  thisByte &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;++&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; (thisByte &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;126&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    thisByte &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;33&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//give the serial port a break.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;  &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//can play with number to check on effectiveness of VTIME settings
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;  delay(&lt;span style=&#34;color:#f5a97f&#34;&gt;2&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;serial-session&#34;&gt;Serial Session&lt;/h3&gt;
&lt;p&gt;Even though I have control of the underlying library now, I still left the serial-port-as-service model set up. It will allow for creating a mock service for testing, or swapping out a port connection based on I/OKit/DriverKit, etc. Maybe even using it to wrap BlueTooth.  It&amp;rsquo;s still a good pattern.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;protocol&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;SerialPortService&lt;/span&gt; {  
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;make&lt;/span&gt;(devicePath:&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;, with:SerialPortConfiguration?) &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; -&amp;gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;Self&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//If a real service, must handle closing and releasing the fileDescriptor&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//on destruction. &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//func close() -&amp;gt; Void&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;write&lt;/span&gt;&amp;lt;T&amp;gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; outBytes:T) &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; -&amp;gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;Int&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;bytesAvailable&lt;/span&gt;() -&amp;gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;Int&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//Never block, only takes whats available&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//Must be careful to not call these too too frequently&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;readIfAvailable&lt;/span&gt;(maxCount:&lt;span style=&#34;color:#91d7e3&#34;&gt;Int&lt;/span&gt;) &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; -&amp;gt; [&lt;span style=&#34;color:#91d7e3&#34;&gt;UInt8&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;readAllAvailable&lt;/span&gt;() &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; -&amp;gt; [&lt;span style=&#34;color:#91d7e3&#34;&gt;UInt8&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;readAvailableLines&lt;/span&gt;(maxLength:&lt;span style=&#34;color:#91d7e3&#34;&gt;Int&lt;/span&gt;) &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; -&amp;gt; (lines:[&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;], remainder:&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;TODO:&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt; make async instead. Currently uses non blocking read.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;readUntil&lt;/span&gt;(oneOf:[&lt;span style=&#34;color:#91d7e3&#34;&gt;UInt8&lt;/span&gt;], orMaxCount maxCount:&lt;span style=&#34;color:#91d7e3&#34;&gt;Int&lt;/span&gt;, tries:&lt;span style=&#34;color:#91d7e3&#34;&gt;Int&lt;/span&gt;) -&amp;gt; [&lt;span style=&#34;color:#91d7e3&#34;&gt;UInt8&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//Uses readEscape configuration. If that&amp;#39;s not set, will never return.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;awaitBytes&lt;/span&gt;(&lt;span style=&#34;color:#91d7e3&#34;&gt;count&lt;/span&gt;:&lt;span style=&#34;color:#91d7e3&#34;&gt;Int&lt;/span&gt;) async -&amp;gt; Result&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;lt;&lt;/span&gt;[&lt;span style=&#34;color:#91d7e3&#34;&gt;UInt8&lt;/span&gt;], Error&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The make() function is pretty straight forward and is in an extension on SwiftSerialPort in the library that needs it. I&amp;rsquo;ve heard that factory methods aren&amp;rsquo;t &amp;ldquo;Swifty&amp;rdquo;, but I think they work really well to not gunkup the original type when conforming to a protocol. A better name for it would be &lt;code&gt;makeForSession&lt;/code&gt;. Either way takes in the now much shorter configuration type.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;SerialPortConfiguration&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;baudRate&lt;/span&gt;: &lt;span style=&#34;color:#91d7e3&#34;&gt;CInt&lt;/span&gt;?
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;readEscape&lt;/span&gt;: (timeOut:&lt;span style=&#34;color:#91d7e3&#34;&gt;UInt8&lt;/span&gt;, byteMin:&lt;span style=&#34;color:#91d7e3&#34;&gt;UInt8&lt;/span&gt;)?
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;I temporarily removed the convenience wrapper on the functions because it was clunky. It&amp;rsquo;s might be a job for a property wrapper or macro? TBD.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//  SerialSession.swift&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//  SerialSession&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//  Created by Carlyn Maw on 8/24/23.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;TODO:&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt; Replace Error types?&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;SwiftSerialPort&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;Foundation&lt;/span&gt; &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//For Data type&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;typealias&lt;/span&gt; SerialSession = BaseSerialSession&amp;lt;SerialPort&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;BaseSerialSession&lt;/span&gt;&amp;lt;Port:SerialPortService&amp;gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;devicePath&lt;/span&gt;:&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;serialPort&lt;/span&gt;:Port?
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;configuration&lt;/span&gt;:SerialPortConfiguration?
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;isOpen&lt;/span&gt;:&lt;span style=&#34;color:#91d7e3&#34;&gt;Bool&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        serialPort &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;!=&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;nil&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;init&lt;/span&gt;(devicePath:&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;         serialPort:Port?,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;         settings:SerialPortConfiguration?) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;.devicePath = devicePath
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;.configuration = settings
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;.serialPort = serialPort
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;.configuration = settings
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;deinit&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        close()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;open&lt;/span&gt;(forcedReset:&lt;span style=&#34;color:#91d7e3&#34;&gt;Bool&lt;/span&gt; = &lt;span style=&#34;color:#f5a97f&#34;&gt;false&lt;/span&gt;) &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Attempting to open port: &lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;devicePath&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; forcedReset &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;||&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;!&lt;/span&gt;isOpen {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            serialPort = &lt;span style=&#34;color:#f5a97f&#34;&gt;nil&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;.serialPort = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; Port.make(devicePath: devicePath, with: configuration)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;close&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        serialPort = &lt;span style=&#34;color:#f5a97f&#34;&gt;nil&lt;/span&gt; &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Port Closed&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;MARK:&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt; SerialSession inits&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;extension&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;BaseSerialSession&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;where&lt;/span&gt; Port == SwiftSerialPort.SerialPort {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;convenience&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;init&lt;/span&gt;(devicePath: &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;, settings:SerialPortConfiguration? = &lt;span style=&#34;color:#f5a97f&#34;&gt;nil&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;port&lt;/span&gt;:Port? = &lt;span style=&#34;color:#f5a97f&#34;&gt;nil&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;do&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            port = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; SerialPort.make(devicePath: devicePath, with: settings)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        } &lt;span style=&#34;color:#c6a0f6&#34;&gt;catch&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Creating session with nil port: &lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;error&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;.&lt;span style=&#34;color:#ed8796&#34;&gt;init&lt;/span&gt;(devicePath: devicePath, serialPort: port,  settings: settings)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;convenience&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;init&lt;/span&gt;(devicePath: &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                     baudRate:&lt;span style=&#34;color:#91d7e3&#34;&gt;CInt&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;       &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;settings&lt;/span&gt; = SerialPortConfiguration(baudRate: baudRate, readEscape: &lt;span style=&#34;color:#f5a97f&#34;&gt;nil&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;.&lt;span style=&#34;color:#ed8796&#34;&gt;init&lt;/span&gt;(devicePath:devicePath, settings:settings)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;TODO:&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt; re-make wrapped?&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;extension&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;BaseSerialSession&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;MARK:&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt; Transmit&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    @discardableResult
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;pingII&lt;/span&gt;() -&amp;gt; Result&amp;lt;&lt;span style=&#34;color:#91d7e3&#34;&gt;Int&lt;/span&gt;, Error&amp;gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;serialPort&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;do&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;bytesWritten&lt;/span&gt; = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; serialPort.write(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;A&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; .success(bytesWritten)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            } &lt;span style=&#34;color:#c6a0f6&#34;&gt;catch&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; .failure(error)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        } &lt;span style=&#34;color:#c6a0f6&#34;&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; .failure(SerialSessionError.noActivePort)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    @discardableResult
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;send&lt;/span&gt;&amp;lt;T&amp;gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; value:T) -&amp;gt; Result&amp;lt;&lt;span style=&#34;color:#91d7e3&#34;&gt;Int&lt;/span&gt;, Error&amp;gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;serialPort&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;do&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;bytesWritten&lt;/span&gt; = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; serialPort.write(value)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; .success(bytesWritten)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            } &lt;span style=&#34;color:#c6a0f6&#34;&gt;catch&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; .failure(error)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        } &lt;span style=&#34;color:#c6a0f6&#34;&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; .failure(SerialSessionError.noActivePort)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;MARK:&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt; Receive&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;readAvailable&lt;/span&gt;() -&amp;gt; Result&amp;lt;Data, Error&amp;gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;serialPort&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;do&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;bytesReceived&lt;/span&gt; = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; serialPort.readAllAvailable()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; bytesReceived.&lt;span style=&#34;color:#91d7e3&#34;&gt;isEmpty&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; .failure(SerialSessionError.noBytesAvailable)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; .success(Data(bytesReceived))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            } &lt;span style=&#34;color:#c6a0f6&#34;&gt;catch&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; .failure(error)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        } &lt;span style=&#34;color:#c6a0f6&#34;&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; .failure(SerialSessionError.noActivePort)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;TODO:&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt; Have Session handle remainders as part of AsyncStream iterator.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;readLines&lt;/span&gt;() -&amp;gt; Result&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;lt;&lt;/span&gt;(lines:[&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;], remainder:&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;), Error&amp;gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;serialPort&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;do&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;dataReceived&lt;/span&gt; = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; serialPort.readAvailableLines(maxLength: &lt;span style=&#34;color:#f5a97f&#34;&gt;1000&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; dataReceived.lines.&lt;span style=&#34;color:#91d7e3&#34;&gt;isEmpty&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; .failure(SerialSessionError.noBytesAvailable)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; .success(dataReceived)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            } &lt;span style=&#34;color:#c6a0f6&#34;&gt;catch&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; .failure(error)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        } &lt;span style=&#34;color:#c6a0f6&#34;&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; .failure(SerialSessionError.noActivePort)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;another-reference-dump&#34;&gt;Another reference dump&lt;/h2&gt;
&lt;p&gt;Several duplicates from last post.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;On your machine, find and open termios.h (macOS spotlight finds it fine.)&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://www.msweet.org/serial/serial.html&#34;&gt;https://www.msweet.org/serial/serial.html&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;other-serial-libraries&#34;&gt;Other Serial Libraries&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/todbot/arduino-serial/&#34;&gt;https://github.com/todbot/arduino-serial/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://swiftpackageindex.com/yeokm1/SwiftSerial&#34;&gt;https://swiftpackageindex.com/yeokm1/SwiftSerial&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;Author&amp;rsquo;s talk: &lt;a href=&#34;https://www.youtube.com/watch?v=6PWP1eZo53s&#34;&gt;https://www.youtube.com/watch?v=6PWP1eZo53s&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://doc.qt.io/qt-6/qserialport.html&#34;&gt;https://doc.qt.io/qt-6/qserialport.html&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;swiftapple-links&#34;&gt;Swift/Apple links&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://developer.apple.com/documentation/iokit&#34;&gt;https://developer.apple.com/documentation/iokit&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://developer.apple.com/documentation/iokit/communicating_with_a_modem_on_a_serial_port&#34;&gt;https://developer.apple.com/documentation/iokit/communicating_with_a_modem_on_a_serial_port&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://developer.apple.com/documentation/driverkit&#34;&gt;https://developer.apple.com/documentation/driverkit&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;if decide to use libusb: &lt;a href=&#34;https://forums.swift.org/t/linking-to-c-libraries/55651/2&#34;&gt;https://forums.swift.org/t/linking-to-c-libraries/55651/2&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man3/tcsetattr.3.html&#34;&gt;https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man3/tcsetattr.3.html&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;cterminos-links&#34;&gt;C/terminos links.&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://tldp.org/HOWTO/Serial-Programming-HOWTO/intro.html&#34;&gt;https://tldp.org/HOWTO/Serial-Programming-HOWTO/intro.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://en.wikibooks.org/wiki/Serial_Programming/termios&#34;&gt;https://en.wikibooks.org/wiki/Serial_Programming/termios&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://man7.org/linux/man-pages/man3/termios.3.html&#34;&gt;https://man7.org/linux/man-pages/man3/termios.3.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://blog.nelhage.com/2009/12/a-brief-introduction-to-termios/&#34;&gt;https://blog.nelhage.com/2009/12/a-brief-introduction-to-termios/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;http://unixwiz.net/techtips/termios-vmin-vtime.html&#34;&gt;http://unixwiz.net/techtips/termios-vmin-vtime.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;talks about open()/fileDescriptors etc: &lt;a href=&#34;https://www.youtube.com/watch?v=BQJBe4IbsvQ&#34;&gt;https://www.youtube.com/watch?v=BQJBe4IbsvQ&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://en.wikibooks.org/wiki/Serial_Programming/termios&#34;&gt;https://en.wikibooks.org/wiki/Serial_Programming/termios&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://www.gnu.org/software/libc/manual/html_node/Setting-Modes.html&#34;&gt;https://www.gnu.org/software/libc/manual/html_node/Setting-Modes.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://stackoverflow.com/questions/31999358/how-are-flags-represented-in-the-termios-library&#34;&gt;https://stackoverflow.com/questions/31999358/how-are-flags-represented-in-the-termios-library&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://circuitdigest.com/tutorial/serial-communication-protocols&#34;&gt;https://circuitdigest.com/tutorial/serial-communication-protocols&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://www.wevolver.com/article/baud-rates-the-most-common-baud-rates&#34;&gt;https://www.wevolver.com/article/baud-rates-the-most-common-baud-rates&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;http://unixwiz.net/techtips/termios-vmin-vtime.html&#34;&gt;http://unixwiz.net/techtips/termios-vmin-vtime.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://www.xanthium.in/Serial-Port-Programming-on-Linux&#34;&gt;https://www.xanthium.in/Serial-Port-Programming-on-Linux&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;arduino&#34;&gt;Arduino&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://www.arduino.cc/reference/en/language/functions/communication/serial/begin/&#34;&gt;https://www.arduino.cc/reference/en/language/functions/communication/serial/begin/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://chrisheydrick.com/2012/06/17/how-to-read-serial-data-from-an-arduino-in-linux-with-c-part-3/&#34;&gt;https://chrisheydrick.com/2012/06/17/how-to-read-serial-data-from-an-arduino-in-linux-with-c-part-3/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</description>
    </item>
    
    
    
    <item>
      <title>Can I open a serial port with Swift? Part I</title>
      <link>https://whynotestflight.com/excuses/can-i-open-a-serial-port-with-swift-part-i/</link>
      <pubDate>Sat, 26 Aug 2023 00:00:00 +0000</pubDate>
      
      <guid>https://whynotestflight.com/excuses/can-i-open-a-serial-port-with-swift-part-i/</guid>
      <description>&lt;p&gt;The answer is yes, on MacOS and Linux. But what I did is maybe sort of cheating?  It uses a library that puts old fashioned C code right in the Swift. No I/OKit, DriverKit, Objective-C libraries. Just C. On one hand it does require turning off Sandbox mode which is a No-No for software destined for the MacOS App Store. On the other hand it works on Linux as well.&lt;/p&gt;
&lt;p&gt;This will not work on iOS, iPad, tvOS, visionOS&amp;hellip; nothing. For that&amp;hellip; use Bluetooth.&lt;/p&gt;
&lt;p&gt;This post represents a brain dump / code dump of the minimal viable working code. I am already working on repos with increasingly restructured code which will be in the next post:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/carlynorama/SerialSession&#34;&gt;https://github.com/carlynorama/SerialSession&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/carlynorama/SerialSessionUI&#34;&gt;https://github.com/carlynorama/SerialSessionUI&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If instead you&amp;rsquo;d like to have this code in the state I left it (no promises):&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;HelloSerialTest.zip&#34;&gt;Library&lt;/a&gt; | &lt;a href=&#34;HelloArduino.zip&#34;&gt;App&lt;/a&gt; | &lt;a href=&#34;ArduinoCode/ForReadView.ino&#34;&gt;Ardunio:ForRead&lt;/a&gt; | &lt;a href=&#34;ArduinoCode/ForWriteView.ino&#34;&gt;Ardunio:ForWrite&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&#34;misc-resources&#34;&gt;Misc Resources&lt;/h2&gt;
&lt;h3 id=&#34;swiftapple-links&#34;&gt;Swift/Apple links&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://developer.apple.com/documentation/iokit/communicating_with_a_modem_on_a_serial_port&#34;&gt;https://developer.apple.com/documentation/iokit/communicating_with_a_modem_on_a_serial_port&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://developer.apple.com/documentation/driverkit&#34;&gt;https://developer.apple.com/documentation/driverkit&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;if decide to use libusb: &lt;a href=&#34;https://forums.swift.org/t/linking-to-c-libraries/55651/2&#34;&gt;https://forums.swift.org/t/linking-to-c-libraries/55651/2&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://apple.stackexchange.com/questions/242104/is-there-a-way-to-access-a-usb-serial-port-by-the-device-id-not-by-the-tty-po&#34;&gt;https://apple.stackexchange.com/questions/242104/is-there-a-way-to-access-a-usb-serial-port-by-the-device-id-not-by-the-tty-po&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;cterminos-links&#34;&gt;C/terminos links.&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://tldp.org/HOWTO/Serial-Programming-HOWTO/intro.html&#34;&gt;https://tldp.org/HOWTO/Serial-Programming-HOWTO/intro.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://en.wikibooks.org/wiki/Serial_Programming/termios&#34;&gt;https://en.wikibooks.org/wiki/Serial_Programming/termios&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://blog.nelhage.com/2009/12/a-brief-introduction-to-termios/&#34;&gt;https://blog.nelhage.com/2009/12/a-brief-introduction-to-termios/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;http://unixwiz.net/techtips/termios-vmin-vtime.html&#34;&gt;http://unixwiz.net/techtips/termios-vmin-vtime.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;talks about open()/fileDescriptors etc: &lt;a href=&#34;https://www.youtube.com/watch?v=BQJBe4IbsvQ&#34;&gt;https://www.youtube.com/watch?v=BQJBe4IbsvQ&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;from-swiftserial&#34;&gt;From SwiftSerial&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://swiftpackageindex.com/yeokm1/SwiftSerial&#34;&gt;https://swiftpackageindex.com/yeokm1/SwiftSerial&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://www.xanthium.in/Serial-Port-Programming-on-Linux&#34;&gt;https://www.xanthium.in/Serial-Port-Programming-on-Linux&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;Book rec: &lt;a href=&#34;https://www.msweet.org/serial/serial.html&#34;&gt;Serial Programming Guide for POSIX Operating Systems by Michael Sweet&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://chrisheydrick.com/2012/06/17/how-to-read-serial-data-from-an-arduino-in-linux-with-c-part-3/&#34;&gt;https://chrisheydrick.com/2012/06/17/how-to-read-serial-data-from-an-arduino-in-linux-with-c-part-3/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Author&amp;rsquo;s talk: &lt;a href=&#34;https://www.youtube.com/watch?v=6PWP1eZo53s&#34;&gt;https://www.youtube.com/watch?v=6PWP1eZo53s&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;whos-connected&#34;&gt;Who&amp;rsquo;s connected&lt;/h2&gt;
&lt;p&gt;There are two main ways to find out what devices are connected and more information about them.&lt;/p&gt;
&lt;p&gt;Frist, since on a POSIX style system everything is a file, using the &lt;code&gt;ls&lt;/code&gt; command to find the devices listed tops the list. Arduino boards will generally show up on a Mac as a &lt;code&gt;/dev/cu.usbmodemXXX&lt;/code&gt; &lt;a href=&#34;https://en.wikipedia.org/wiki/Device_file&#34;&gt;device file&lt;/a&gt; where the XXX will be replaced by some number.  They&amp;rsquo;ll be listed as a &lt;a href=&#34;https://en.wikipedia.org/wiki/Computer_terminal&#34;&gt;tty&lt;/a&gt; device file as well.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ls /dev/cu.* &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# &amp;#34;calling unit&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# results on my machine:  /dev/cu.Bluetooth-Incoming-Port	/dev/cu.usbmodem1101&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ls /dev/tty.* &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# TeleTYpes&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#/dev/tty.usbmodem1101&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Note that Arduino boards get listed as modems because they fall in the category of virtual &lt;a href=&#34;https://en.wikipedia.org/wiki/USB_communications_device_class&#34;&gt;serial communication devices&lt;/a&gt; known as CDC/ACM devices (Communication Device Class/Abstract Control Model). They do not implement the &lt;a href=&#34;https://en.wikipedia.org/wiki/Hayes_AT_command_set&#34;&gt;Hayes AT command set&lt;/a&gt; which what one might think of as what qualifies as &amp;ldquo;being a modem&amp;rdquo; if one had used them in the past.&lt;/p&gt;
&lt;p&gt;Second, on MacOS specifically you can use the &lt;a href=&#34;https://developer.apple.com/library/archive/documentation/DeviceDrivers/Conceptual/IOKitFundamentals/TheRegistry/TheRegistry.html&#34;&gt;I/O Kit Device Registry&lt;/a&gt; lookup utility to find out lots of information about the USB devices hooked up to the computer. &lt;a href=&#34;https://apple.stackexchange.com/questions/242104/is-there-a-way-to-access-a-usb-serial-port-by-the-device-id-not-by-the-tty-po&#34;&gt;more info&lt;/a&gt;&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ioreg -p IOUSB
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ioreg -r -c IOUSBHostDevice -l
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;usage: ioreg &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;[&lt;/span&gt;-abfilrtxy&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;]&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;[&lt;/span&gt;-c class&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;]&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;[&lt;/span&gt;-d depth&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;]&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;[&lt;/span&gt;-k key&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;]&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;[&lt;/span&gt;-n name&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;]&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;[&lt;/span&gt;-p plane&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;]&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;[&lt;/span&gt;-w width&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;where options are:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	-a archive output
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	-b show object name in bold
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	-c list properties of objects with the given class
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	-d limit tree to the given depth
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	-f &lt;span style=&#34;color:#91d7e3&#34;&gt;enable&lt;/span&gt; smart formatting
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	-i show object inheritance
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	-k list properties of objects with the given key
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	-l list properties of all objects
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	-n list properties of objects with the given name
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	-p traverse registry over the given plane &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;(&lt;/span&gt;IOService is default&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	-r show subtrees rooted by the given criteria
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	-t show location of each subtree
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	-w clip output to the given line width &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#f5a97f&#34;&gt;0&lt;/span&gt; is unlimited&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	-x show data and numbers as hexadecimal
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	-y &lt;span style=&#34;color:#c6a0f6&#34;&gt;do&lt;/span&gt; not consider DriverKit classes with -c
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;put-and-arduino-in-serial-loop-back-mode&#34;&gt;Put and Arduino in Serial Loop Back Mode&lt;/h2&gt;
&lt;p&gt;&amp;ldquo;Hello World&amp;rdquo; on the library I picked requires using Serial Loop Back mode.&lt;/p&gt;
&lt;p&gt;I recommend using an old fashioned &lt;a href=&#34;https://store-usa.arduino.cc/products/arduino-uno-rev3?selectedStore=us&#34;&gt;Uno R3 board&lt;/a&gt;, as they definitely can do it (external driver chips).&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://support.arduino.cc/hc/en-us/articles/360020366520-How-to-do-a-loopback-test&#34;&gt;https://support.arduino.cc/hc/en-us/articles/360020366520-How-to-do-a-loopback-test&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&#34;picking-a-library&#34;&gt;Picking a Library&lt;/h2&gt;
&lt;p&gt;After quite a bit of poking around I decided to get up and running with the &lt;a href=&#34;https://github.com/yeokm1/SwiftSerial&#34;&gt;SwiftSerial&lt;/a&gt; library. It&amp;rsquo;s small and uses C commands I&amp;rsquo;m already familiar with.&lt;/p&gt;
&lt;h2 id=&#34;swiftserial-hello-world&#34;&gt;SwiftSerial &amp;ldquo;Hello World&amp;rdquo;&lt;/h2&gt;
&lt;p&gt;To side step the issues of entitlements I decided to set up a package. (&lt;code&gt;swift package init --type executable&lt;/code&gt;)&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// swift-tools-version: 5.8&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// The swift-tools-version declares the minimum version of Swift required to build this package.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;PackageDescription&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;package&lt;/span&gt; = Package(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    name: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;HelloSerialTest&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    products: [
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        .executable(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            name: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;HelloSerialTest&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            targets: [&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;HelloSerialTest&amp;#34;&lt;/span&gt;]),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    ],
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    dependencies: [
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        .package(url: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;https://github.com/yeokm1/swiftserial.git&amp;#34;&lt;/span&gt;, from: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;0.1.2&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    ],
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    targets: [
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        .executableTarget(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            name: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;HelloSerialTest&amp;#34;&lt;/span&gt;, 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            dependencies: [
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                .product(name: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;SwiftSerial&amp;#34;&lt;/span&gt;, package: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;swiftserial&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            ]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        ),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        .testTarget(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            name: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;HelloSerialTestTests&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            dependencies: [&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;HelloSerialTest&amp;#34;&lt;/span&gt;]),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    ]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//  HelloSerialTest.swift&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//  HelloArduino&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//  Created by Carlyn Maw on 8/24/23.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;@main
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;HelloSerialTest&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;main&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;test&lt;/span&gt; = EchoTest(portName: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;/dev/cu.usbmodem1101&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        test.run()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;I copied the example code from &lt;code&gt;SwiftSerial&lt;/code&gt; into a struct so I wouldn&amp;rsquo;t have to build it separately as it says in &lt;a href=&#34;https://github.com/yeokm1/SwiftSerial/blob/4e46944053c9dd5b0340aeed4772d68bc371c04e/README.md?plain=1#L57&#34;&gt;the instructions&lt;/a&gt;. I did do that. It did work. However, this is about adding the code to my own projects.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//  EchoTest.swift&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//  HelloArduino&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//  Created by Carlyn Maw on 8/24/23.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;Foundation&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;SwiftSerial&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;EchoTest&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;testString&lt;/span&gt;: &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt; = &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;The quick brown fox jumps over the lazy dog 01234567890.&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;numberOfMultiNewLineTest&lt;/span&gt; : &lt;span style=&#34;color:#91d7e3&#34;&gt;Int&lt;/span&gt; = &lt;span style=&#34;color:#f5a97f&#34;&gt;5&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;portName&lt;/span&gt;:&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;serialPort&lt;/span&gt;: SerialPort
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;init&lt;/span&gt;(portName: &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;.portName = portName
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;.serialPort = SerialPort(path: portName)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;run&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;You should do a loopback i.e short the TX and RX pins of the target serial port before testing.&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;do&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Attempting to open port: &lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;portName&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; serialPort.openPort()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Serial port &lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;portName&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt; opened successfully.&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;defer&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                serialPort.closePort()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Port Closed&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            serialPort.setSettings(receiveRate: .baud9600,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                                   transmitRate: .baud9600,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                                   minimumBytesToRead: &lt;span style=&#34;color:#f5a97f&#34;&gt;1&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Writing test string &amp;lt;&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;testString&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;gt; of &lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;testString.&lt;span style=&#34;color:#91d7e3&#34;&gt;count&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt; characters to serial port&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;bytesWritten&lt;/span&gt; = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; serialPort.writeString(testString)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Successfully wrote &lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;bytesWritten&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt; bytes&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Waiting to receive what was written...&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;stringReceived&lt;/span&gt; = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; serialPort.readString(ofLength: bytesWritten)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; testString == stringReceived {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Received string is the same as transmitted string. Test successful!&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            } &lt;span style=&#34;color:#c6a0f6&#34;&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Uh oh! Received string is not the same as what was transmitted. This was what we received,&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&amp;lt;&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;stringReceived&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;gt;&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Now testing reading/writing of &lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;numberOfMultiNewLineTest&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt; lines&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;multiLineString&lt;/span&gt;: &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt; = &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;for&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;1.&lt;/span&gt;..numberOfMultiNewLineTest {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                multiLineString &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;+=&lt;/span&gt; testString &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;+&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\n&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Now writing multiLineString&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;_&lt;/span&gt; = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; serialPort.writeString(multiLineString)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;for&lt;/span&gt; i &lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;1.&lt;/span&gt;..numberOfMultiNewLineTest {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;stringReceived&lt;/span&gt; = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; serialPort.readLine()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                  
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; testString == stringReceived {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    &lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Received string &lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;i&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt; is the same as transmitted section. Moving on...&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                } &lt;span style=&#34;color:#c6a0f6&#34;&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    &lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Uh oh! Received string &lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;i&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt; is not the same as what was transmitted. This was what we received,&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    &lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&amp;lt;&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;stringReceived&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;gt;&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    &lt;span style=&#34;color:#c6a0f6&#34;&gt;break&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;End of example&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        } &lt;span style=&#34;color:#c6a0f6&#34;&gt;catch&lt;/span&gt; PortError.failedToOpen {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Serial port &lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;portName&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt; failed to open. You might need root permissions.&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        } &lt;span style=&#34;color:#c6a0f6&#34;&gt;catch&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Error: &lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;error&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And it all worked!&lt;/p&gt;
&lt;h2 id=&#34;adding-it-to-an-app&#34;&gt;Adding it to an App&lt;/h2&gt;
&lt;p&gt;Add the package using the link: &lt;a href=&#34;https://github.com/yeokm1/swiftserial.git&#34;&gt;https://github.com/yeokm1/swiftserial.git&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;I did set the USB Entitlements:
&lt;img src=&#34;usb_setting.png&#34; alt=&#34;Screenshot of how to set the USB Entitlements&#34;&gt;&lt;/p&gt;
&lt;p&gt;And turn off the Sandbox:
&lt;img src=&#34;turn_off_sandbox.png&#34; alt=&#34;Screenshot of the entitlements file open with the Sandbox setting set to off&#34;&gt;&lt;/p&gt;
&lt;p&gt;I did not set &lt;code&gt;com.apple.security.device.serial&lt;/code&gt; in the entitlements file, but I will try that in the future to see if it lets me turn the SandBox back on. &lt;a href=&#34;https://github.com/yeokm1/SwiftSerial/issues/18&#34;&gt;reference&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I added the same &lt;code&gt;EchoTest.swift&lt;/code&gt; file from the package, and updated the default &lt;code&gt;ContentView()&lt;/code&gt;&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//  ContentView.swift&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//  HelloArduino&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//  Created by Carlyn Maw on 8/24/23.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;SwiftUI&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;ContentView&lt;/span&gt;: View {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    @State &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;echoTest&lt;/span&gt;:EchoTest = EchoTest(portName: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;/dev/cu.usbmodem1101&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    @State &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;brightness&lt;/span&gt;:&lt;span style=&#34;color:#91d7e3&#34;&gt;Double&lt;/span&gt; = &lt;span style=&#34;color:#f5a97f&#34;&gt;0.5&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;body&lt;/span&gt;: some View {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        VStack {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            Image(systemName: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;globe&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                .imageScale(.large)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                .foregroundColor(.accentColor)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            Text(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Hello, world!&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        .padding()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        .onAppear() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            echoTest.run()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Works again!&lt;/p&gt;
&lt;h2 id=&#34;interacting-with-the-arduino-more-realistically&#34;&gt;Interacting with the Arduino more realistically&lt;/h2&gt;
&lt;p&gt;Arduino a while back decided that having to hold down the reset pin in order to upload code onto them was too fiddly. So now, every time one opens the serial port, the whole board resets, waiting to receive new instructions for a split second before proceeding. They do this by linking the &lt;a href=&#34;https://en.wikipedia.org/wiki/Data_Terminal_Ready&#34;&gt;DTR line&lt;/a&gt; to the reset pin. It can be turned off (cut the trace, add a cap) but that&amp;rsquo;s not the norm.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://forum.arduino.cc/t/does-arduino-reset-when-first-connected-to-usb/544278/&#34;&gt;https://forum.arduino.cc/t/does-arduino-reset-when-first-connected-to-usb/544278/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This means that it&amp;rsquo;s important to not be opening and closing that serial port too often. I created a class that could be made an observable object, not to publish a value at this time, but to persist the connection.&lt;/p&gt;
&lt;p&gt;The tricky business in this class is that I want to option to persist the connection, or not. This means a wrapper for every call, checking to see if the class thinks the port is open. This setup is not ideal. At some point I will have to go into &lt;code&gt;SwiftSerial&lt;/code&gt; and create a function to ask the port itself if it&amp;rsquo;s open, etc.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//  SerialManager.swift&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//  HelloArduino&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//  Created by Carlyn Maw on 8/24/23.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;Foundation&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;SwiftSerial&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;SerialManager&lt;/span&gt;:ObservableObject {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;portName&lt;/span&gt;:&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;serialPort&lt;/span&gt;: SerialPort
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;maintainConnection&lt;/span&gt;:&lt;span style=&#34;color:#91d7e3&#34;&gt;Bool&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;isOpen&lt;/span&gt;:&lt;span style=&#34;color:#91d7e3&#34;&gt;Bool&lt;/span&gt; = &lt;span style=&#34;color:#f5a97f&#34;&gt;false&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;init&lt;/span&gt;(portName: &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;, maintainConnection:&lt;span style=&#34;color:#91d7e3&#34;&gt;Bool&lt;/span&gt; = &lt;span style=&#34;color:#f5a97f&#34;&gt;true&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;.portName = portName
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;.serialPort = SerialPort(path: portName)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;.maintainConnection = maintainConnection
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; maintainConnection {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;.safeOpen()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;deinit&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        close()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;open&lt;/span&gt;() &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Attempting to open port: &lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;portName&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; serialPort.openPort()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Serial port &lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;portName&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt; opened successfully.&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        serialPort.setSettings(receiveRate: .baud9600,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                               transmitRate: .baud9600, minimumBytesToRead: &lt;span style=&#34;color:#f5a97f&#34;&gt;1&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        isOpen = &lt;span style=&#34;color:#f5a97f&#34;&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;safeOpen&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;do&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; open()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        } &lt;span style=&#34;color:#c6a0f6&#34;&gt;catch&lt;/span&gt; PortError.failedToOpen {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            isOpen = &lt;span style=&#34;color:#f5a97f&#34;&gt;false&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Serial port &lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;portName&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt; failed to open.&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        } &lt;span style=&#34;color:#c6a0f6&#34;&gt;catch&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#91d7e3&#34;&gt;fatalError&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Error: &lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;error&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;close&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        serialPort.closePort()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Port Closed&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        isOpen = &lt;span style=&#34;color:#f5a97f&#34;&gt;false&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;private&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;wrappedThrowing&lt;/span&gt;&amp;lt;I, R&amp;gt;(function:(I) &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; -&amp;gt; R, parameter:I) -&amp;gt; Result&amp;lt;R,Error&amp;gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;defer&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;!&lt;/span&gt;maintainConnection { close() }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;do&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;!&lt;/span&gt;isOpen { &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; open() }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;r&lt;/span&gt; = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; function(parameter)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; .success(r)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        } &lt;span style=&#34;color:#c6a0f6&#34;&gt;catch&lt;/span&gt; PortError.failedToOpen {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Serial port &lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;portName&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt; failed to open.&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; .failure(PortError.failedToOpen)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        } &lt;span style=&#34;color:#c6a0f6&#34;&gt;catch&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#91d7e3&#34;&gt;fatalError&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Error: &lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;error&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    @discardableResult
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;pingII&lt;/span&gt;() -&amp;gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;Int&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;defer&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;!&lt;/span&gt;maintainConnection { close() }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;do&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;!&lt;/span&gt;isOpen { &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; open() }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;bytesWritten&lt;/span&gt; = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; serialPort.writeString(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;A&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; bytesWritten
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        } &lt;span style=&#34;color:#c6a0f6&#34;&gt;catch&lt;/span&gt; PortError.failedToOpen {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Serial port &lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;portName&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt; failed to open.&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;-&lt;/span&gt;&lt;span style=&#34;color:#f5a97f&#34;&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        } &lt;span style=&#34;color:#c6a0f6&#34;&gt;catch&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;TODO:&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt; catch other errors&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#91d7e3&#34;&gt;fatalError&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Error: &lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;error&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    @discardableResult
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;sendByte&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; byte:&lt;span style=&#34;color:#91d7e3&#34;&gt;UInt8&lt;/span&gt;) -&amp;gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;Int&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;pingII&lt;/span&gt;() -&amp;gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;Int&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;defer&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;!&lt;/span&gt;maintainConnection { close() }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;do&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;!&lt;/span&gt;isOpen { &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; open() }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;m_message&lt;/span&gt; = byte
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;bytesWritten&lt;/span&gt; =  &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; serialPort.writeBytes(from: &amp;amp;m_message, size: &lt;span style=&#34;color:#f5a97f&#34;&gt;1&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; bytesWritten
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            } &lt;span style=&#34;color:#c6a0f6&#34;&gt;catch&lt;/span&gt; PortError.failedToOpen {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Serial port &lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;portName&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt; failed to open.&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;-&lt;/span&gt;&lt;span style=&#34;color:#f5a97f&#34;&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            } &lt;span style=&#34;color:#c6a0f6&#34;&gt;catch&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;TODO:&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt; catch other errors&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#91d7e3&#34;&gt;fatalError&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Error: &lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;error&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;-&lt;/span&gt;&lt;span style=&#34;color:#f5a97f&#34;&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;With this code loaded on the Arduino:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-Cpp&#34; data-lang=&#34;Cpp&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;/*
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;  Variation on Dimmer example. 
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;  https://www.arduino.cc/en/Tutorial/BuiltInExamples/Dimmer
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;The circuit:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;  - LED attached from digital pin 9 to ground through 220 ohm resistor.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;  - LED attached to digital pin 6 to power via a 220 ohm resistor (sinking).
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;  - Serial connection to Processing, Max/MSP, or another serial application
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;  Edited Carlyn Maw 2023 Aug 24
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;*/&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;const&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;int&lt;/span&gt; ledPin &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;9&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;const&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;int&lt;/span&gt; noSignalPin &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;6&lt;/span&gt;; 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;unsigned&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;long&lt;/span&gt; previousMillis &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;0&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;const&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;long&lt;/span&gt; interval &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;30&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;byte brightness &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;0&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;void&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;setup&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// initialize the serial communication:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;  Serial.begin(&lt;span style=&#34;color:#f5a97f&#34;&gt;9600&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// initialize the ledPin as an output:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;  pinMode(ledPin, OUTPUT);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  analogWrite(ledPin, &lt;span style=&#34;color:#f5a97f&#34;&gt;0&lt;/span&gt;); &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//LOW is off because anode is wired to Arduino
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//ADDITION TO DIMMER CODE
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;  pinMode(noSignalPin, OUTPUT);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  digitalWrite(noSignalPin, HIGH);  &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//HIGH is off because cathode is wired to Arduino
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;void&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;loop&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#ed8796&#34;&gt;unsigned&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;long&lt;/span&gt; currentMillis &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; millis();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; (Serial.available()) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    digitalWrite(noSignalPin, HIGH);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    brightness &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; Serial.read();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  } &lt;span style=&#34;color:#c6a0f6&#34;&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;     &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; (currentMillis &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;-&lt;/span&gt; previousMillis &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;gt;=&lt;/span&gt; interval) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      previousMillis &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; currentMillis;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; (brightness &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;0&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        brightness &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; brightness &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;-&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;1&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;     }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;     digitalWrite(noSignalPin, LOW);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  analogWrite(ledPin, brightness);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And content view updated to:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//  ContentView.swift&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//  HelloArduino&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//  Created by Carlyn Maw on 8/24/23.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;SwiftUI&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;ContentView&lt;/span&gt;: View {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    @StateObject &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;serialWriter&lt;/span&gt;:SerialManager = SerialManager(portName: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;/dev/cu.usbmodem11201&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    @State &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;brightness&lt;/span&gt;:&lt;span style=&#34;color:#91d7e3&#34;&gt;Double&lt;/span&gt; = &lt;span style=&#34;color:#f5a97f&#34;&gt;0.5&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;body&lt;/span&gt;: some View {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        VStack {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            Slider(value: &lt;span style=&#34;color:#ed8796&#34;&gt;$&lt;/span&gt;brightness) { editing &lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;!&lt;/span&gt;editing {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;val&lt;/span&gt; = &lt;span style=&#34;color:#91d7e3&#34;&gt;UInt8&lt;/span&gt;(brightness &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;*&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;255&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    &lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(val)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    serialWriter.sendByte(val)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        .padding()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        .onAppear() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            serialWriter.pingII()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;My LEDs behaved and dimmed as expected. Success!&lt;/p&gt;
&lt;h2 id=&#34;reading-serial&#34;&gt;Reading Serial&lt;/h2&gt;
&lt;p&gt;The &lt;code&gt;SerialManager&lt;/code&gt; got some upgrades to reduce boiler plate once I added the read functions. I&amp;rsquo;ve also changed the return types to result builders to prep for async. The below code all works together, but it has some serious problems. First of all the program will hang if the Arduino is connected but not sending serial information. I tried changing one of the settings in the &lt;code&gt;SwiftSerial&lt;/code&gt; library that is supposed to fix that. It did not. That may be on me and I will try again. Second, SwiftSerial has no flush command to nuke the buffer and get the latest readings when the button is pressed. It&amp;rsquo;s now pretty certain that I will be making some changes to my copy of &lt;code&gt;SwiftSerial&lt;/code&gt;, but as written it&amp;rsquo;s still an incredibly helpful bootstrap.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//  SerialManager.swift&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//  HelloArduino&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//  Created by Carlyn Maw on 8/24/23.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;Foundation&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;SwiftSerial&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;SerialManager&lt;/span&gt;:ObservableObject {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;portName&lt;/span&gt;:&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;serialPort&lt;/span&gt;: SerialPort
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;maintainConnection&lt;/span&gt;:&lt;span style=&#34;color:#91d7e3&#34;&gt;Bool&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;isOpen&lt;/span&gt;:&lt;span style=&#34;color:#91d7e3&#34;&gt;Bool&lt;/span&gt; = &lt;span style=&#34;color:#f5a97f&#34;&gt;false&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;init&lt;/span&gt;(portName: &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;, maintainConnection:&lt;span style=&#34;color:#91d7e3&#34;&gt;Bool&lt;/span&gt; = &lt;span style=&#34;color:#f5a97f&#34;&gt;true&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;.portName = portName
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;.serialPort = SerialPort(path: portName)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;.maintainConnection = maintainConnection
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; maintainConnection {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//print(&amp;#34;safe open&amp;#34;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;.safeOpen()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;deinit&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        close()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;open&lt;/span&gt;() &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Attempting to open port: &lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;portName&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; serialPort.openPort()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Serial port &lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;portName&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt; opened successfully.&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        serialPort.setSettings(receiveRate: .baud9600,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                               transmitRate: .baud9600, minimumBytesToRead: &lt;span style=&#34;color:#f5a97f&#34;&gt;1&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        isOpen = &lt;span style=&#34;color:#f5a97f&#34;&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;safeOpen&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;do&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; open()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        } &lt;span style=&#34;color:#c6a0f6&#34;&gt;catch&lt;/span&gt; PortError.failedToOpen {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            isOpen = &lt;span style=&#34;color:#f5a97f&#34;&gt;false&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Serial port &lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;portName&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt; failed to open.&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        } &lt;span style=&#34;color:#c6a0f6&#34;&gt;catch&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;TODO:&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt; Handle other errors&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#91d7e3&#34;&gt;fatalError&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Error: &lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;error&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;close&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        serialPort.closePort()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Port Closed&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        isOpen = &lt;span style=&#34;color:#f5a97f&#34;&gt;false&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;private&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;wrappedThrowing&lt;/span&gt;&amp;lt;I, R&amp;gt;(function:(I) &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; -&amp;gt; R, parameter:I) -&amp;gt; Result&amp;lt;R,Error&amp;gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;defer&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;!&lt;/span&gt;maintainConnection { close() }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;do&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;!&lt;/span&gt;isOpen { &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; open() }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;r&lt;/span&gt; = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; function(parameter)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; .success(r)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        } &lt;span style=&#34;color:#c6a0f6&#34;&gt;catch&lt;/span&gt; PortError.failedToOpen {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Serial port &lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;portName&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt; failed to open.&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; .failure(PortError.failedToOpen)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        } &lt;span style=&#34;color:#c6a0f6&#34;&gt;catch&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;TODO:&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt; Handle other errors&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#91d7e3&#34;&gt;fatalError&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Error: &lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;error&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    @discardableResult
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;pingII&lt;/span&gt;() -&amp;gt; Result&amp;lt;&lt;span style=&#34;color:#91d7e3&#34;&gt;Int&lt;/span&gt;, Error&amp;gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; wrappedThrowing(function: serialPort.writeString, parameter: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;A&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    @discardableResult
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;sendByte&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; byte:&lt;span style=&#34;color:#91d7e3&#34;&gt;UInt8&lt;/span&gt;) -&amp;gt; Result&amp;lt;&lt;span style=&#34;color:#91d7e3&#34;&gt;Int&lt;/span&gt;, Error&amp;gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; wrappedThrowing(function: writeByteWrapper, parameter: byte)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;private&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;writeByteWrapper&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; byte:&lt;span style=&#34;color:#91d7e3&#34;&gt;UInt8&lt;/span&gt;) &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt;  -&amp;gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;Int&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;m_message&lt;/span&gt; = byte
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; serialPort.writeBytes(from: &amp;amp;m_message, size: &lt;span style=&#34;color:#f5a97f&#34;&gt;1&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;readBytes&lt;/span&gt;(&lt;span style=&#34;color:#91d7e3&#34;&gt;count&lt;/span&gt;:&lt;span style=&#34;color:#91d7e3&#34;&gt;Int&lt;/span&gt;) -&amp;gt; Result&amp;lt;Data, Error&amp;gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; wrappedThrowing(function: serialPort.readData, parameter: &lt;span style=&#34;color:#91d7e3&#34;&gt;count&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;readLine&lt;/span&gt;() -&amp;gt; Result&amp;lt;&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;, Error&amp;gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; wrappedThrowing(function: serialPort.readUntilChar, parameter: &lt;span style=&#34;color:#91d7e3&#34;&gt;CChar&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;10&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Arduino Code:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-cpp&#34; data-lang=&#34;cpp&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;/*
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;  Exactly the example code:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;  https://www.arduino.cc/en/Tutorial/BuiltInExamples/Graph
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;*/&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;void&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;setup&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// initialize the serial communication:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;  Serial.begin(&lt;span style=&#34;color:#f5a97f&#34;&gt;9600&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;void&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;loop&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// send the value of analog input 0:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;  Serial.println(analogRead(A0));
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// wait a bit for the analog-to-digital converter to stabilize after the last
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;  &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// reading:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;  delay(&lt;span style=&#34;color:#f5a97f&#34;&gt;2&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And a ReadView:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//  ReadView.swift&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//  HelloArduino&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//  Created by Carlyn Maw on 8/24/23.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;SwiftUI&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;ReadView&lt;/span&gt;: View {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    @StateObject &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;serialReader&lt;/span&gt;:SerialManager = SerialManager(portName: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;/dev/cu.usbmodem11201&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    @State &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;reading&lt;/span&gt;:&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt; = &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;body&lt;/span&gt;: some View {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        VStack {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            Text(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;reading&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            Button(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Read&amp;#34;&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                updateText()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        .padding()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        .onAppear() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            serialReader.pingII()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;updateText&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//let result = serialReader.readLine()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;result&lt;/span&gt; = serialReader.readBytes(&lt;span style=&#34;color:#91d7e3&#34;&gt;count&lt;/span&gt;: &lt;span style=&#34;color:#f5a97f&#34;&gt;256&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;switch&lt;/span&gt; result {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;case&lt;/span&gt; .success(&lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;message&lt;/span&gt;):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            reading = &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;(data: message, encoding: .utf8)&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;!&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;case&lt;/span&gt; .failure(&lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;error&lt;/span&gt;):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(error)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description>
    </item>
    
    
    
    <item>
      <title>What about some fancier C&#43;&#43; in with the Swift?</title>
      <link>https://whynotestflight.com/excuses/what-about-some-fancier-c-in-with-the-swift/</link>
      <pubDate>Tue, 15 Aug 2023 00:00:00 +0000</pubDate>
      
      <guid>https://whynotestflight.com/excuses/what-about-some-fancier-c-in-with-the-swift/</guid>
      <description>&lt;p&gt;The &lt;a href=&#34;https://whynotestflight.com/excuses/cmake-overview/&#34;&gt;CMake &amp;ldquo;Hello World&amp;rdquo;&lt;/a&gt; prime number provider code seemed like a fun thing to try to bring into this &lt;a href=&#34;https://whynotestflight.com/excuses/time-for-c-and-swift-to-make-first-contact/&#34;&gt;new Swift/C++ Package&lt;/a&gt;. The file loading requirement made it a tricky choice, but it provided good practice importing C++ classes into Swift.&lt;/p&gt;
&lt;h2 id=&#34;related-repo&#34;&gt;Related Repo&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/carlynorama/CxxInteropLibrary/blob/2023_08_14/&#34;&gt;https://github.com/carlynorama/CxxInteropLibrary/blob/2023_08_14/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;references&#34;&gt;References&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://developer.apple.com/videos/play/wwdc2023/10172/&#34;&gt;https://developer.apple.com/videos/play/wwdc2023/10172/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://www.swift.org/documentation/cxx-interop/&#34;&gt;https://www.swift.org/documentation/cxx-interop/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;templates&#34;&gt;Templates&lt;/h2&gt;
&lt;p&gt;The random-number generator that creates the index number used to go fetch a prime number from the file uses &lt;a href=&#34;https://learn.microsoft.com/en-us/cpp/cpp/templates-cpp?view=msvc-170&#34;&gt;C++ templates&lt;/a&gt;. Swift can interact with those a little bit, but not perfectly. A post on the forums provide a good break down of the issues:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://forums.swift.org/t/bridging-c-templates-with-interop/55003&#34;&gt;https://forums.swift.org/t/bridging-c-templates-with-interop/55003&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;It&amp;rsquo;s not a big barrier to get this example working since the call to &lt;code&gt;fancy_random&lt;/code&gt; will be internal to its class in the end (&lt;a href=&#34;#PNG&#34;&gt;see below&lt;/a&gt;), but I tired it out anyway.&lt;/p&gt;
&lt;p&gt;A reminder of the C++:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-cpp&#34; data-lang=&#34;cpp&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;template&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;typename&lt;/span&gt; T&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;gt;&lt;/span&gt; T fancy_random(&lt;span style=&#34;color:#c6a0f6&#34;&gt;const&lt;/span&gt; T &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;amp;&lt;/span&gt;min, &lt;span style=&#34;color:#c6a0f6&#34;&gt;const&lt;/span&gt; T &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;amp;&lt;/span&gt;max) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   std&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;::&lt;/span&gt;random_device seed_maker;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   std&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;::&lt;/span&gt;mt19937 generator(seed_maker()); &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// Random-number engine to use (Mersenne-Twister)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;   std&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;::&lt;/span&gt;uniform_int_distribution&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;lt;&lt;/span&gt;T&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;gt;&lt;/span&gt; distribution(min,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                                                 max); &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// Guaranteed unbiased
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;   &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;distribution&lt;/span&gt;(generator);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;A successful swift call:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;randomInt&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;min&lt;/span&gt;:CUnsignedChar, &lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;max&lt;/span&gt;:CUnsignedChar) -&amp;gt; CUnsignedChar {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        fancy_random(&lt;span style=&#34;color:#91d7e3&#34;&gt;min&lt;/span&gt;, &lt;span style=&#34;color:#91d7e3&#34;&gt;max&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Unsuccessful Swift calls. (causes linker errors)&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   &lt;span style=&#34;color:#ed8796&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;randomNumber&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;min&lt;/span&gt;:&lt;span style=&#34;color:#91d7e3&#34;&gt;UInt8&lt;/span&gt;, &lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;max&lt;/span&gt;:&lt;span style=&#34;color:#91d7e3&#34;&gt;UInt8&lt;/span&gt;) -&amp;gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;UInt8&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;       fancy_random(&lt;span style=&#34;color:#91d7e3&#34;&gt;min&lt;/span&gt;, &lt;span style=&#34;color:#91d7e3&#34;&gt;max&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;randomNumber&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;min&lt;/span&gt;:&lt;span style=&#34;color:#91d7e3&#34;&gt;CUnsignedInt&lt;/span&gt;, &lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;max&lt;/span&gt;:&lt;span style=&#34;color:#91d7e3&#34;&gt;CUnsignedInt&lt;/span&gt;) -&amp;gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;CUnsignedInt&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    fancy_random(&lt;span style=&#34;color:#91d7e3&#34;&gt;min&lt;/span&gt;, &lt;span style=&#34;color:#91d7e3&#34;&gt;max&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Bug report filed: &lt;a href=&#34;https://github.com/apple/swift/issues/67901&#34;&gt;https://github.com/apple/swift/issues/67901&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&#34;accessing-the-bundle&#34;&gt;Accessing the Bundle&lt;/h2&gt;
&lt;p&gt;In order to test moving files around with CMake, I designed the prime number library code to load and scan a file with prime numbers in it. Packages with resource files need to access those resources via a &lt;a href=&#34;https://developer.apple.com/documentation/xcode/bundling-resources-with-a-swift-package&#34;&gt;Bundle&lt;/a&gt; type.&lt;/p&gt;
&lt;p&gt;There MAY be a way to massage the C++ to import either &lt;code&gt;NSBundle&lt;/code&gt; or the Swift type &lt;code&gt;Bundle&lt;/code&gt;, but it&amp;rsquo;s way above my current pay grade. I haven&amp;rsquo;t even been able to successfully get my hands on &lt;a href=&#34;https://www.swift.org/documentation/cxx-interop/#using-swift-standard-library-types-from-c&#34;&gt;&lt;code&gt;swift::String&lt;/code&gt;&lt;/a&gt; yet.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/apple/swift-package-manager/blob/48192bbdd2800a38a82fa658a244e70b3167ec5d/Sources/Build/BuildDescription/ClangTargetBuildDescription.swift#L304-L364&#34;&gt;https://github.com/apple/swift-package-manager/blob/48192bbdd2800a38a82fa658a244e70b3167ec5d/Sources/Build/BuildDescription/ClangTargetBuildDescription.swift#L304-L364&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://forums.swift.org/t/access-a-package-s-bundle-module-from-c-c/63339&#34;&gt;https://forums.swift.org/t/access-a-package-s-bundle-module-from-c-c/63339&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;A &lt;code&gt;Bundle&lt;/code&gt; related side bar: It looks like the Swift 5.9 Package Manager Tools now has an automated &lt;a href=&#34;https://github.com/search?q=repo%3Aapple%2Fswift-package-manager%20embedInCode&amp;amp;type=code&#34;&gt;.embedInCode&lt;/a&gt; option? It looks the accessor is a dictionary? I wonder how that will work from the C++? To. Do. Very handy, even just for Swift.&lt;/p&gt;
&lt;p&gt;Creating a placeholder class in C++ called &lt;code&gt;BundleManger&lt;/code&gt; provided an immediate work around for not being able to get my hands on &lt;code&gt;Bundle&lt;/code&gt;. A &lt;code&gt;BundleManger&lt;/code&gt; gets initialized with a path string generated by the Swift target&amp;rsquo;s &lt;code&gt;Bundle&lt;/code&gt; reference. In this case, the Swift library was given a mock resource file so &lt;code&gt;Bundle.module&lt;/code&gt; would exist. This code relies on the Swift target&amp;rsquo;s and the C++ target&amp;rsquo;s resource bundles having the same root path. Very fragile.&lt;/p&gt;
&lt;p&gt;It&amp;rsquo;s my understanding from the WWDC video that &lt;code&gt;BundleManager&lt;/code&gt; should be passed into Swift as a value type by default, even though it&amp;rsquo;s a class. I did not confirm it.&lt;/p&gt;
&lt;h3 id=&#34;thingcatalogswift&#34;&gt;ThingCatalog.swift&lt;/h3&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;Foundation&lt;/span&gt; &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//for Bundle&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#eed49f&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;cxxLibrary&lt;/span&gt;  &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// for my class&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;ThingCatalog&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;bundleManager&lt;/span&gt;:BundleManager &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//SO! EASY!!!&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;init&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;strippedPath&lt;/span&gt; = &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;(URL(filePath: Bundle.module.bundlePath)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            .deletingLastPathComponent()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            .path())
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;.bundleManager = BundleManager(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            std.string(strippedPath), 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;CxxInteropLibrary_cxxLibrary.bundle&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            )
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;In the call to initialize a &lt;code&gt;BundleManager&lt;/code&gt; note the &lt;code&gt;std.string()&lt;/code&gt; casting of a Swift string into the C++ standard library string the initializer requires. The ability to draw upon C++ standard library types gets enabled in the package when &lt;code&gt;swiftSettings: [.interoperabilityMode(.Cxx)]),&lt;/code&gt; gets added to the target&amp;rsquo;s definition in &lt;code&gt;Package.swift&lt;/code&gt;. In order to refer to &lt;code&gt;stdlib&lt;/code&gt; types one must import at least one of the following&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;a C++ product that imports the desired standard library types in its own headers&lt;/li&gt;
&lt;li&gt;&lt;code&gt;CxxStdlib&lt;/code&gt; - Bug report: &lt;a href=&#34;https://github.com/apple/swift/issues/67946&#34;&gt;compiler warning but not failure&lt;/a&gt; if no companion lib imported?&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Foundation&lt;/code&gt; - it&amp;rsquo;s bad practice to go importing Foundation willy nilly. However, if it&amp;rsquo;s needed anyway, &lt;code&gt;CxxStdLib&lt;/code&gt; appears to come for the ride IF the projects build setting is C++/Objective C++ mode. This hold true for XCode projects updated via the GUI as well.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The &amp;ldquo;overlay implementations&amp;rdquo; are still being actively worked on. String actually seems the most fleshed out.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/apple/swift/tree/main/stdlib/public/Cxx&#34;&gt;https://github.com/apple/swift/tree/main/stdlib/public/Cxx&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://duckduckgo.com/?q=overlay+implementation+GSOC+forums.swift.org&#34;&gt;https://duckduckgo.com/?q=overlay+implementation+GSOC+forums.swift.org&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;bundlemanagerhpp&#34;&gt;BundleManager.hpp&lt;/h3&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-cpp&#34; data-lang=&#34;cpp&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#ifndef BundleManager_hpp
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#define BundleManager_hpp
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#include&lt;/span&gt; &lt;span style=&#34;color:#6e738d;font-weight:bold;font-style:italic&#34;&gt;&amp;lt;stdio.h&amp;gt;&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#include&lt;/span&gt; &lt;span style=&#34;color:#6e738d;font-weight:bold;font-style:italic&#34;&gt;&amp;lt;string&amp;gt;&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#include&lt;/span&gt; &lt;span style=&#34;color:#6e738d;font-weight:bold;font-style:italic&#34;&gt;&amp;lt;swift/bridging&amp;gt;&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//allows for annotating
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;BundleManager&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;public&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    BundleManager(std&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;::&lt;/span&gt;string path, std&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;::&lt;/span&gt;string name) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        bundle_path &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; path;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        this_bundle_name &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; name;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    std&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;::&lt;/span&gt;string path() &lt;span style=&#34;color:#c6a0f6&#34;&gt;const&lt;/span&gt; SWIFT_COMPUTED_PROPERTY {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; bundle_path;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    std&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;::&lt;/span&gt;string name() &lt;span style=&#34;color:#c6a0f6&#34;&gt;const&lt;/span&gt; SWIFT_COMPUTED_PROPERTY {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; this_bundle_name;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    std&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;::&lt;/span&gt;string path_for_resource(std&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;::&lt;/span&gt;string name, std&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;::&lt;/span&gt;string extension);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;private&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    std&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;::&lt;/span&gt;string bundle_path;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    std&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;::&lt;/span&gt;string this_bundle_name;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;};
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#endif &lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;/* BundleManager_hpp */&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;bundlemanagercpp&#34;&gt;BundleManager.cpp&lt;/h3&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-cpp&#34; data-lang=&#34;cpp&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;std&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;::&lt;/span&gt;string BundleManager&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;::&lt;/span&gt;path_for_resource(std&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;::&lt;/span&gt;string name, std&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;::&lt;/span&gt;string extension) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; bundle_path &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;+&lt;/span&gt; this_bundle_name &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;+&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;/&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;+&lt;/span&gt; name &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;+&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;.&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;+&lt;/span&gt; extension;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This whole approach worked to get a valid path into C++, but without additional structure every prime number retrieving function call would of had to collect that information as a parameter. Yuck.&lt;/p&gt;
&lt;h2 id=&#34;PNG&#34;&gt;Making PrimeNumberGenerator class&lt;/h2&gt;
&lt;p&gt;Instead of rewriting all the functions, I made a &lt;code&gt;PrimeNumberGenerator&lt;/code&gt; object that holds a &lt;code&gt;BundleManager&lt;/code&gt; privately.&lt;/p&gt;
&lt;p&gt;I could have made &lt;code&gt;PrimeNumberGenerator&lt;/code&gt; a subclass of &lt;code&gt;BundleManager&lt;/code&gt;, but the nuances of how the many shades of class inheritance in C++ maps into Swift requires more study on my part. I&amp;rsquo;m just going to avoid that for the moment.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/apple/swift/issues/66323&#34;&gt;https://github.com/apple/swift/issues/66323&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://forums.swift.org/t/swift-c-interop-and-polymorphism/66103&#34;&gt;https://forums.swift.org/t/swift-c-interop-and-polymorphism/66103&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I did, however, want to try out making an explicit reference type.&lt;/p&gt;
&lt;h3 id=&#34;primenumbergeneratorhpp&#34;&gt;PrimeNumberGenerator.hpp&lt;/h3&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-cpp&#34; data-lang=&#34;cpp&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#ifndef PrimeNumberGenerator_hpp
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#define PrimeNumberGenerator_hpp
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#include&lt;/span&gt; &lt;span style=&#34;color:#6e738d;font-weight:bold;font-style:italic&#34;&gt;&amp;lt;stdio.h&amp;gt;&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#include&lt;/span&gt; &lt;span style=&#34;color:#6e738d;font-weight:bold;font-style:italic&#34;&gt;&amp;lt;string&amp;gt;&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#include&lt;/span&gt; &lt;span style=&#34;color:#6e738d;font-weight:bold;font-style:italic&#34;&gt;&amp;lt;swift/bridging&amp;gt;&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//allows for annotating
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;BundleManager&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//this lives here now
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;};
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;PrimeNumberGenerator&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;public&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    PrimeNumberGenerator(std&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;::&lt;/span&gt;string bundle_path)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;:&lt;/span&gt;bundle(bundle_path, &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;CxxInteropLibrary_cxxLibrary.bundle&amp;#34;&lt;/span&gt;), 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    max_line_length(&lt;span style=&#34;color:#f5a97f&#34;&gt;16&lt;/span&gt;), &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// Max line is 12 characters long
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;    max_prime_length(&lt;span style=&#34;color:#f5a97f&#34;&gt;6&lt;/span&gt;)  &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//// 10,000th prime is 104729
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;    {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//prime in first 10000 primes at index
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;int&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;prime_at&lt;/span&gt;(&lt;span style=&#34;color:#ed8796&#34;&gt;int&lt;/span&gt; index);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//random prime within first 10000 primes
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;int&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;random_prime&lt;/span&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;private&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//All for file loading. 
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;    BundleManager bundle;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;const&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;int&lt;/span&gt; max_line_length;     
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;const&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;int&lt;/span&gt; max_prime_length;     
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;int&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;readNthLine&lt;/span&gt;(std&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;::&lt;/span&gt;ifstream &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;amp;&lt;/span&gt;in, &lt;span style=&#34;color:#ed8796&#34;&gt;int&lt;/span&gt; index);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;template&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;typename&lt;/span&gt; T&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;gt;&lt;/span&gt; T fancy_random(&lt;span style=&#34;color:#c6a0f6&#34;&gt;const&lt;/span&gt; T &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;amp;&lt;/span&gt;min, &lt;span style=&#34;color:#c6a0f6&#34;&gt;const&lt;/span&gt; T &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;amp;&lt;/span&gt;max);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;unsigned&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;char&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;random_uint8&lt;/span&gt;(&lt;span style=&#34;color:#c6a0f6&#34;&gt;const&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;unsigned&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;char&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;amp;&lt;/span&gt;min, &lt;span style=&#34;color:#c6a0f6&#34;&gt;const&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;unsigned&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;char&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;amp;&lt;/span&gt;max);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}; SWIFT_SHARED_REFERENCE(pngRetain,pngRelease); 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//At the bottom or top? Seen both. Which style is preferred? 
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;void&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;pngRetain&lt;/span&gt;(PrimeNumberGenerator &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;*&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;void&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;pngRelease&lt;/span&gt;(PrimeNumberGenerator &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;*&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#endif &lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;/* PrimeNumberGenerator_hpp */&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;primenumbergeneratorcpp&#34;&gt;PrimeNumberGenerator.cpp&lt;/h3&gt;
&lt;p&gt;This will look pretty similar to &lt;a href=&#34;https://github.com/carlynorama/Hello_Cpp_Using_VSCode/blob/main/MultiFileExample/source/PrimeLib.cpp&#34;&gt;PrimeLib.cpp&lt;/a&gt;, just with class namespace prefixes.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-cpp&#34; data-lang=&#34;cpp&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//  PrimeNumberGenerator.cpp
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//  
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//  Created by Carlyn Maw on 8/13/23.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#include&lt;/span&gt; &lt;span style=&#34;color:#6e738d;font-weight:bold;font-style:italic&#34;&gt;&amp;#34;PrimeNumberGenerator.hpp&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#include&lt;/span&gt; &lt;span style=&#34;color:#6e738d;font-weight:bold;font-style:italic&#34;&gt;&amp;lt;fstream&amp;gt;&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#include&lt;/span&gt; &lt;span style=&#34;color:#6e738d;font-weight:bold;font-style:italic&#34;&gt;&amp;lt;random&amp;gt;&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#include&lt;/span&gt; &lt;span style=&#34;color:#6e738d;font-weight:bold;font-style:italic&#34;&gt;&amp;lt;string&amp;gt;&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//Same as before.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;std&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;::&lt;/span&gt;string BundleManager&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;::&lt;/span&gt;path_for_resource(std&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;::&lt;/span&gt;string name, std&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;::&lt;/span&gt;string extension) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; bundle_path &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;+&lt;/span&gt; this_bundle_name &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;+&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;/&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;+&lt;/span&gt; name &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;+&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;.&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;+&lt;/span&gt; extension;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;int&lt;/span&gt; PrimeNumberGenerator&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;::&lt;/span&gt;readNthLine(std&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;::&lt;/span&gt;ifstream &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;amp;&lt;/span&gt;in, &lt;span style=&#34;color:#ed8796&#34;&gt;int&lt;/span&gt; index) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;for&lt;/span&gt; (&lt;span style=&#34;color:#ed8796&#34;&gt;int&lt;/span&gt; i &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;0&lt;/span&gt;; i &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;lt;&lt;/span&gt; index &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;-&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;1&lt;/span&gt;; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;++&lt;/span&gt;i) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        in.ignore(max_line_length, &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#39;\n&amp;#39;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    std&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;::&lt;/span&gt;string s;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    s.reserve(max_prime_length);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    std&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;::&lt;/span&gt;getline(in.ignore(max_line_length, &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#39; &amp;#39;&lt;/span&gt;), s);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; std&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;::&lt;/span&gt;stoi(s);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;uint8_t&lt;/span&gt; PrimeNumberGenerator&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;::&lt;/span&gt;random_uint8(&lt;span style=&#34;color:#c6a0f6&#34;&gt;const&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;uint8_t&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;amp;&lt;/span&gt;min, &lt;span style=&#34;color:#c6a0f6&#34;&gt;const&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;uint8_t&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;amp;&lt;/span&gt;max) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;fancy_random&lt;/span&gt;(min, max);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;template&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;typename&lt;/span&gt; T&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;gt;&lt;/span&gt; T PrimeNumberGenerator&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;::&lt;/span&gt;fancy_random(&lt;span style=&#34;color:#c6a0f6&#34;&gt;const&lt;/span&gt; T &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;amp;&lt;/span&gt;min, &lt;span style=&#34;color:#c6a0f6&#34;&gt;const&lt;/span&gt; T &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;amp;&lt;/span&gt;max) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    std&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;::&lt;/span&gt;random_device seed_maker;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    std&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;::&lt;/span&gt;mt19937 generator(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        seed_maker()); &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// Random-number engine to use (Mersenne-Twister)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;    std&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;::&lt;/span&gt;uniform_int_distribution&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;lt;&lt;/span&gt;T&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;gt;&lt;/span&gt; distribution(min,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                                                  max); &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// Guaranteed unbiased
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;distribution&lt;/span&gt;(generator);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// random prime within first 10000 primes
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;int&lt;/span&gt; PrimeNumberGenerator&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;::&lt;/span&gt;random_prime() { &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;prime_at&lt;/span&gt;(fancy_random(&lt;span style=&#34;color:#f5a97f&#34;&gt;0&lt;/span&gt;, &lt;span style=&#34;color:#f5a97f&#34;&gt;10000&lt;/span&gt;)); }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// prime in first 10000 primes at index
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;int&lt;/span&gt; PrimeNumberGenerator&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;::&lt;/span&gt;prime_at(&lt;span style=&#34;color:#ed8796&#34;&gt;int&lt;/span&gt; index) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//assumes package uses .process for resources
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;    std&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;::&lt;/span&gt;ifstream primesFile(bundle.path_for_resource(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;b000040&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;txt&amp;#34;&lt;/span&gt;));
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; (primesFile.is_open()) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;readNthLine&lt;/span&gt;(primesFile, index);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    } &lt;span style=&#34;color:#c6a0f6&#34;&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// handle error
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;-&lt;/span&gt;&lt;span style=&#34;color:#f5a97f&#34;&gt;1&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;add-the-test-and-run&#34;&gt;Add the Test, and run&lt;/h2&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;XCTest&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;@testable &lt;span style=&#34;color:#ed8796&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;InteropLibrary&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;final&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;CxxInteropLibraryTests&lt;/span&gt;: XCTestCase {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;MARK:&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt; PrimeNumberGenerator Related&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;testChosenPrime&lt;/span&gt;() &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;things&lt;/span&gt; = ThingCatalog()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        XCTAssertEqual(things.nthPrime(n: &lt;span style=&#34;color:#f5a97f&#34;&gt;998&lt;/span&gt;), &lt;span style=&#34;color:#f5a97f&#34;&gt;7901&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Once that&amp;rsquo;s in, a quick pop over to Terminal and a &lt;code&gt;swift test&lt;/code&gt; shows that it all works! Whew!&lt;/p&gt;
</description>
    </item>
    
    
    
    <item>
      <title>Time for C&#43;&#43; and Swift to make first Contact</title>
      <link>https://whynotestflight.com/excuses/time-for-c-and-swift-to-make-first-contact/</link>
      <pubDate>Thu, 10 Aug 2023 00:00:00 +0000</pubDate>
      
      <guid>https://whynotestflight.com/excuses/time-for-c-and-swift-to-make-first-contact/</guid>
      <description>&lt;p&gt;As mentioned in a post a &lt;a href=&#34;https://whynotestflight.com/excuses/hello-c-my-old-friend./&#34;&gt;few days a go&lt;/a&gt;, I&amp;rsquo;m walking through the same process with C++ interop as I did with C.&lt;/p&gt;
&lt;p&gt;Yesterday I hit two of the bases:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A project for testing C++ and Swift in the same source base in the context of a an XCode project&lt;/li&gt;
&lt;li&gt;A project with C++ and Swift in the same Library.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;All this required the XCode 15 beta (No.6) and Swift version 5.9 (swiftlang-5.9.0.128.2 clang-1500.0.40.1)&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;m going to flesh the library one out a bit more, I think, but they both got to hello world!&lt;/p&gt;
&lt;h2 id=&#34;references&#34;&gt;References&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://developer.apple.com/videos/play/wwdc2023/10172/&#34;&gt;https://developer.apple.com/videos/play/wwdc2023/10172/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://developer.apple.com/documentation/Swift/MixingLanguagesInAnXcodeProject&#34;&gt;https://developer.apple.com/documentation/Swift/MixingLanguagesInAnXcodeProject&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://www.swift.org/documentation/cxx-interop/&#34;&gt;https://www.swift.org/documentation/cxx-interop/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://www.swift.org/documentation/cxx-interop/project-build-setup/&#34;&gt;https://www.swift.org/documentation/cxx-interop/project-build-setup/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://developer.apple.com/documentation/swift/callingapisacrosslanguageboundaries&#34;&gt;https://developer.apple.com/documentation/swift/callingapisacrosslanguageboundaries&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;related-repos&#34;&gt;Related Repos&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/carlynorama/CppInteropSimplestXCode/&#34;&gt;https://github.com/carlynorama/CppInteropSimplestXCode/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/carlynorama/CxxInteropLibrary/tree/simple&#34;&gt;https://github.com/carlynorama/CxxInteropLibrary/tree/simple&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;in-xcode&#34;&gt;In XCode&lt;/h2&gt;
&lt;h3 id=&#34;make-the-project&#34;&gt;Make the project&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Selected multi-target project&lt;/li&gt;
&lt;li&gt;Updated &lt;code&gt;Swift Compiler - Language&lt;/code&gt; build settings for project to &lt;code&gt;C++/ObjectiveC++&lt;/code&gt; (filter on &amp;ldquo;interop&amp;rdquo;, its at the bottom) &lt;a href=&#34;https://developer.apple.com/videos/play/wwdc2023/10172/&#34;&gt;Time Code 2:56&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;add-c-files&#34;&gt;Add C++ files&lt;/h3&gt;
&lt;p&gt;Choose the options to create header AND bridging header.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-C++&#34; data-lang=&#34;C++&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//  CxxExampleCode.hpp
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//  CppInteropInlineExample
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//  Created by Carlyn Maw on 8/9/23.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#ifndef CxxExampleCode_hpp
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#define CxxExampleCode_hpp
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#include&lt;/span&gt; &lt;span style=&#34;color:#6e738d;font-weight:bold;font-style:italic&#34;&gt;&amp;lt;stdio.h&amp;gt;&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;int&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;myFavoriteNumber&lt;/span&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#endif &lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;/* CxxExampleCode_hpp */&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-C++&#34; data-lang=&#34;C++&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//  CxxExampleCode.cpp
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//  CppInteropInlineExample
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//  Created by Carlyn Maw on 8/9/23.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#include&lt;/span&gt; &lt;span style=&#34;color:#6e738d;font-weight:bold;font-style:italic&#34;&gt;&amp;#34;CxxExampleCode.hpp&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;int&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;myFavoriteNumber&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;5&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-c++&#34; data-lang=&#34;c++&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//  CppInteropInlineExample-Bridging-Header.h
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//  CppInteropInlineExample
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//  Created by Carlyn Maw on 8/9/23.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//  Use this file to import your target&amp;#39;s public headers that you would like to expose to Swift.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#include&lt;/span&gt; &lt;span style=&#34;color:#6e738d;font-weight:bold;font-style:italic&#34;&gt;&amp;#34;SimpleCxxFunctions.hpp&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;add-call-to-c-in-contentviewswift&#34;&gt;Add call to C++ in ContentView.swift&lt;/h3&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;ContentView&lt;/span&gt;: View {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;number&lt;/span&gt; = myFavoriteNumber()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;body&lt;/span&gt;: some View {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        VStack {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            Image(systemName: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;globe&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                .imageScale(.large)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                .foregroundStyle(.tint)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            Text(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Hello, No. &lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;number&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;!&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        .padding()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Done! Pretty identical to the &lt;a href=&#34;(/excuses/but-some-of-my-best-friends-are-c/)&#34;&gt;process with C&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;swift-calling-c-in-a-library&#34;&gt;Swift Calling C++ In a Library&lt;/h2&gt;
&lt;h3 id=&#34;begin-project&#34;&gt;Begin Project&lt;/h3&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;cd $PROJECT_DIR
swift package init --type library
touch README.md
git init
&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=&#34;update-package-file&#34;&gt;Update Package File&lt;/h3&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// swift-tools-version: 5.9&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// The swift-tools-version declares the minimum version of Swift required to build this package.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;PackageDescription&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;package&lt;/span&gt; = Package(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    name: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;CxxInteropLibrary&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    products: [
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        .library(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            name: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;cxxLibrary&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            targets: [&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;cxxLibrary&amp;#34;&lt;/span&gt;]),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        .library(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            name: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;InteropLibrary&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            targets: [&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;InteropLibrary&amp;#34;&lt;/span&gt;]),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        ],
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    targets: [
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        .target(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            name: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;cxxLibrary&amp;#34;&lt;/span&gt;),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        .target(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            name: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;InteropLibrary&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            dependencies: [&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;cxxLibrary&amp;#34;&lt;/span&gt;],
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//IMPORTANT include for _any_ target that uses Swift calling C++, not just executables.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            swiftSettings: [.interoperabilityMode(.Cxx)]),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        .testTarget(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            name: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;CxxInteropLibraryTests&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            dependencies: [&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;InteropLibrary&amp;#34;&lt;/span&gt;],
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            swiftSettings: [.interoperabilityMode(.Cxx)])
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    ]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;create-directory-structure&#34;&gt;Create Directory Structure&lt;/h3&gt;
&lt;p&gt;The general outline for the project. The key is that the sub folders in the Sources directory are named the same as the products/targets and that all the cpp header files end up in the include folder. The source folder names are easy to change via the package file. Having the header files somewhere other than the include folder requires more doing.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-txt&#34; data-lang=&#34;txt&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;└── Project
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    └── Sources
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    │   └── cxxLibrary
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    |   |   |── include
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    |   |   |   └── module.modulemap
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    |   |   |   └── SimpleCxxFunctions.hpp
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    |   |   └── SimpleCxxFunctions.cpp
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    |   └── InteropLibrary
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    |       └── SomeSwiftFile.swift
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    └── Tests
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        └── ...
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The module map looks like:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;module cxxLibrary {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    header &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;SimpleCxxFunctions.hpp&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    export &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;*&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The &lt;a href=&#34;https://www.swift.org/documentation/cxx-interop/#importing-c-into-swift&#34;&gt;documentation says&lt;/a&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&amp;ldquo;Swift Package Manager automatically generates a module map file when it finds an umbrella header in a C++ target. Xcode automatically generates a module map file for a framework target, with the module map referencing framework’s public headers. In other cases you might be required to create a module map manually.&amp;rdquo;&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;I tried making an umbrella header file in include called cxxLibrary.h, but the SPM did not in fact seem able to pick up on it in either Xcode or VScode so I went with the modulemap, which I had &lt;a href=&#34;https://whynotestflight.com/excuses/can-i-get-my-hands-on-a-homebrew-installed-library/&#34;&gt;used before&lt;/a&gt; when bringing in a system installed C library.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#incude &amp;lt;cxxLibrary/someCPPFile.hpp&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;add-the-c&#34;&gt;Add the C++&lt;/h3&gt;
&lt;p&gt;This project used the same C++ files as the Xcode project to get started, minus the bridging header. Also &lt;code&gt;myFavoriteNumber&lt;/code&gt; returns &amp;ldquo;5&amp;rdquo;.&lt;/p&gt;
&lt;h3 id=&#34;add-the-swift&#34;&gt;Add the Swift&lt;/h3&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//  /InteropLibrary/ThingCatalog.swift&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//  CxxInteropLibrary&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//  Created by Carlyn Maw on 8/9/23.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;cxxLibrary&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;ThingCatalog&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;init&lt;/span&gt;() {}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;currentNumber&lt;/span&gt;() -&amp;gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;Int&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;Int&lt;/span&gt;(myFavoriteNumber())
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;add-the-test&#34;&gt;Add the Test&lt;/h3&gt;
&lt;p&gt;As a way of getting out of building a CLI to test the framework, I just built actual tests. It can then be tested in Xcode or with &lt;code&gt;swift test&lt;/code&gt; from the command line (in the project directory).&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;XCTest&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;@testable &lt;span style=&#34;color:#ed8796&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;InteropLibrary&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;final&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;CxxInteropLibraryTests&lt;/span&gt;: XCTestCase {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;testCurrentNumber&lt;/span&gt;() &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        XCTAssert(ThingCatalog().currentNumber() == &lt;span style=&#34;color:#f5a97f&#34;&gt;5&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This test passes!&lt;/p&gt;
&lt;p&gt;Up next, try different C++ functions with different types.&lt;/p&gt;
</description>
    </item>
    
    
    
    <item>
      <title>CMake Overview</title>
      <link>https://whynotestflight.com/excuses/cmake-overview/</link>
      <pubDate>Tue, 08 Aug 2023 00:00:00 +0000</pubDate>
      
      <guid>https://whynotestflight.com/excuses/cmake-overview/</guid>
      <description>&lt;p&gt;Historically I&amp;rsquo;ve built C++ as tiny specific programs for tiny specific chips. This means not even using regular &lt;a href=&#34;https://gcc.gnu.org&#34;&gt;gcc&lt;/a&gt;, but &lt;a href=&#34;https://gcc.gnu.org/wiki/avr-gcc&#34;&gt;avr-gcc&lt;/a&gt; or &lt;a href=&#34;https://developer.arm.com/downloads/-/gnu-rm&#34;&gt;arm-gcc&lt;/a&gt;. Honestly I haven&amp;rsquo;t even used clang a ton until starting with Swift. I&amp;rsquo;ve written Makefiles, and run the occasional provided CMake file. Understanding CMake has hardly been necessary since CMake shines for large software projects that need to be built on several platforms and that isn&amp;rsquo;t what I&amp;rsquo;ve generally done.&lt;/p&gt;
&lt;p&gt;Now however, OpenUSD has a pretty impressive build script and resulting CMake files that I&amp;rsquo;d like to understand better if I may ultimately have to do a specialized build of it.  Also, if I&amp;rsquo;m going to mix C++ and Swift, understanding the build systems better will only help.&lt;/p&gt;
&lt;h2 id=&#34;simplest-cmake&#34;&gt;Simplest CMake&lt;/h2&gt;
&lt;p&gt;The simplest main CMake file (always called CMakeLists.txt) has 3 parts&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-cmake&#34; data-lang=&#34;cmake&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#PART 1: Minimum Version of CMake file is valid for
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#91d7e3&#34;&gt;cmake_minimum_required&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;VERSION&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;3.24&lt;/span&gt;)&lt;span style=&#34;color:#ed8796&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#PART 2: Project Name (technically optional)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#91d7e3&#34;&gt;project&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;Hello&lt;/span&gt;)&lt;span style=&#34;color:#ed8796&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#PART 3: Executable Target name and files list
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#91d7e3&#34;&gt;add_executable&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;ClickHello&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;HelloWorld.cpp&lt;/span&gt;)&lt;span style=&#34;color:#ed8796&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Imagine a project with this layout:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;└── Project
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    └── source
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    │   └── CMakeLists.txt
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    |   └── HelloWorld.cpp
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    └── build
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        └── nothing yet...
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;To build the source files into the build folder there are a couple of ways to go about it:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-zsh&#34; data-lang=&#34;zsh&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# The classic Style&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#91d7e3&#34;&gt;cd&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;$BUILD_DIR&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;cmake &lt;span style=&#34;color:#f4dbd6&#34;&gt;$SOURCE_DIR&lt;/span&gt; &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# the location of the CMakeLists.txt&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;make &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# assumes CMake made Makefiles&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;./&lt;span style=&#34;color:#f4dbd6&#34;&gt;$EXECUTABLE_NAME&lt;/span&gt; &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#run the code&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## Modern Style&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#91d7e3&#34;&gt;cd&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;$SOURCE_DIR&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;cmake -S . -B ../build 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;cmake --build ../build &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#can be run no matter the build system&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;../build/&lt;span style=&#34;color:#f4dbd6&#34;&gt;$EXECUTABLE_NAME&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The &lt;a href=&#34;Makefile_simplest_to_compare.txt&#34;&gt;makefile generated&lt;/a&gt; by this simplest of processes already has huge amounts more thrown in than the ones I&amp;rsquo;ve &lt;a href=&#34;https://whynotestflight.com/excuses/so-what-if-i-wanted-to-write-some-c-with-no-swift/&#34;&gt;written in the past&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;example-cmake-for-multi-file-project&#34;&gt;Example CMake for Multi-File Project&lt;/h2&gt;
&lt;p&gt;To test CMake for a multi-file project, I made a simple prime number supplier project with the following file layout:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;└── Project
    └── source
    │   └── CMakeLists.txt
    |   └── resources
    |   |   └── prime_numbers.txt
    |   └── Prime.cpp
    |   └── PrimeLib.cpp
    |   └── PrimeLib.hpp    
    └── build
        └── PrimeEmitter
        └── resources
            └── prime_numbers.txt
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Note that the text file with the primes is copied into the build folder (at compile time), NOT mashed into the binary. That&amp;rsquo;s accomplished by the last part of the CMakeLists.txt:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-cmake&#34; data-lang=&#34;cmake&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# Set the minimum required version
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#91d7e3&#34;&gt;cmake_minimum_required&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;VERSION&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;3.24&lt;/span&gt;)&lt;span style=&#34;color:#ed8796&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# Project Information
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#91d7e3&#34;&gt;project&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;Primes&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#a6da95&#34;&gt;VERSION&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;0.0.1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#a6da95&#34;&gt;DESCRIPTION&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Complete Miscellany&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#a6da95&#34;&gt;LANGUAGES&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;CXX&lt;/span&gt;)  &lt;span style=&#34;color:#ed8796&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#Name the library and the files it uses         
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#91d7e3&#34;&gt;add_library&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;PrimeNumberStore&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;PrimeLib.cpp&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;PrimeLib.hpp&lt;/span&gt;)&lt;span style=&#34;color:#ed8796&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# Name the Executable Target and say which files it uses
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#91d7e3&#34;&gt;add_executable&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;PrimeEmitter&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;Prime.cpp&lt;/span&gt;)&lt;span style=&#34;color:#ed8796&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#91d7e3&#34;&gt;target_compile_features&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;PrimeEmitter&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;PRIVATE&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;cxx_std_20&lt;/span&gt;)&lt;span style=&#34;color:#ed8796&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# Link the library
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#91d7e3&#34;&gt;target_link_libraries&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;PrimeEmitter&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;PRIVATE&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;PrimeNumberStore&lt;/span&gt;)&lt;span style=&#34;color:#ed8796&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# Example of add_custom_command(), Move a Resources Folder
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# Uses cleaner $&amp;lt;TARGET_FILE_DIR:PrimeEmitter&amp;gt; instead of ${CMAKE_CURRENT_BINARY_DIR}
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#91d7e3&#34;&gt;add_custom_command&lt;/span&gt;(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	&lt;span style=&#34;color:#a6da95&#34;&gt;TARGET&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;PrimeEmitter&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;POST_BUILD&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	&lt;span style=&#34;color:#a6da95&#34;&gt;COMMAND&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;${&lt;/span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;CMAKE_COMMAND&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;}&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;-E&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;copy_directory&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;		&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;${&lt;/span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;CMAKE_SOURCE_DIR&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;}&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;/resources&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;$&amp;lt;&lt;/span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;TARGET_FILE_DIR:PrimeEmitter&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;gt;&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;/resources&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;)&lt;span style=&#34;color:#ed8796&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ul&gt;
&lt;li&gt;Scroll down after resources to see files inline or &lt;a href=&#34;https://github.com/carlynorama/Hello_Cpp_Using_VSCode/tree/main/MultiFileExample/source&#34;&gt;on github&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;It all worked great using:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#91d7e3&#34;&gt;cd&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;$PROJECT_FOLDER&lt;/span&gt;/source
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;cmake -S . -B ../build &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# must do prep&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;cmake --build ../build &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# before can build&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;../build/PrimeEmitter &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# gives random prime&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;../build/PrimeEmitter &lt;span style=&#34;color:#f5a97f&#34;&gt;3&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;998&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;9999&lt;/span&gt; &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# gives 3rd, 998th and 9999th prime&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;references&#34;&gt;References&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;The book everyone recommends: &lt;a href=&#34;https://crascit.com/professional-cmake/&#34;&gt;https://crascit.com/professional-cmake/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Best overview video by &amp;ldquo;C++ Weekly With Jason Turner&amp;rdquo; and some updates
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://www.youtube.com/watch?v=HPMvU64RUTY&#34;&gt;episode 78&lt;/a&gt; Overview of what CMake does. Simple. Fast. This is the winner.&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://www.youtube.com/watch?v=YbgH7yat-Jo&amp;amp;t=0s&#34;&gt;episode 208&lt;/a&gt;, Catalog of C++ CMake options. Dense. A reference not a how to.&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://www.youtube.com/watch?v=ucl0cw9X3e8&#34;&gt;episode 376&lt;/a&gt; 2023 Update, also dense. Again, a reference for those already knowledgeable.&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/cpp-best-practices/gui_starter_template&#34;&gt;Older Repo mentioned in 78 (GUI Starter)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/cpp-best-practices/cmake_template&#34;&gt;2023 Repo from 376(CMake Template)&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Nice CMake syntax overview: &lt;a href=&#34;https://llvm.org/docs/CMakePrimer.html&#34;&gt;https://llvm.org/docs/CMakePrimer.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;I got those from this &lt;a href=&#34;https://gist.github.com/mbinna/c61dbb39bca0e4fb7d1f73b0d66a4fd1&#34;&gt;excellent list of tips&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Which I got from this reference: &lt;a href=&#34;https://cliutils.gitlab.io/modern-cmake/&#34;&gt;https://cliutils.gitlab.io/modern-cmake/&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;Extra useful: &lt;a href=&#34;https://cliutils.gitlab.io/modern-cmake/chapters/basics/structure.html&#34;&gt;https://cliutils.gitlab.io/modern-cmake/chapters/basics/structure.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Example Projects: &lt;a href=&#34;https://gitlab.com/CLIUtils/modern-cmake/-/tree/master/examples&#34;&gt;https://gitlab.com/CLIUtils/modern-cmake/-/tree/master/examples&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://kubasejdak.com/19-reasons-why-cmake-is-actually-awesome&#34;&gt;https://kubasejdak.com/19-reasons-why-cmake-is-actually-awesome&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://www.youtube.com/watch?v=lZ4VytXLNSo&amp;amp;list=PL-UNXjSqcu61LEUuH5PIk2VOsnlaVhKju&#34;&gt;CMake Series by Riley Entertainment Games&lt;/a&gt; Gets to the point. Vaguely follows along with official tutorial.
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/ryantherileyman/cmake-testing-grounds/tree/main&#34;&gt;Companion GitHub project&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://www.youtube.com/watch?v=rHjZrJmFyBQ&amp;amp;list=PLQMs5svASiXOraccrnEbkd_kVHbAdC2mp&#34;&gt;Extensive video intro series&lt;/a&gt;. Windows &amp;amp; Linux focused. Can really &lt;a href=&#34;https://www.youtube.com/watch?v=4gl2szb6d4Q&amp;amp;list=PLQMs5svASiXOraccrnEbkd_kVHbAdC2mp&amp;amp;index=2&amp;amp;t=863s&#34;&gt;skip to 14:23 in the to second video&lt;/a&gt; unless need help setting up from 0.  Very very detailed. Great for people starting utterly from scratch.
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/rutura/CMakeSeries&#34;&gt;Companion GitHub project&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://cmake.org/cmake/help/latest/guide/tutorial/index.html&#34;&gt;Official Tutorial&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://cmake.org/cmake/help/latest/_downloads/cf4565f3e911b7a28033c00995a0c74a/cmake-3.27.1-tutorial-source.zip&#34;&gt;tutorial files download&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;An interesting &amp;ldquo;Best Practices&amp;rdquo; video to watch AFTER some familiarity with CMake files. CppCon 2017: Mathieu Ropert “&lt;a href=&#34;https://www.youtube.com/watch?v=eC9-iRN2b04&#34;&gt;Using Modern CMake Patterns to Enforce a Good Modular Design&lt;/a&gt;”&lt;/li&gt;
&lt;li&gt;Also not an introduction, ~2hrs &lt;a href=&#34;https://www.youtube.com/watch?v=rLopVhns4Zs&#34;&gt;Daniel Pfeifer - &amp;ldquo;Effective CMake&amp;rdquo;&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;file-contents-for-multi-file-project&#34;&gt;File Contents for Multi-File project&lt;/h2&gt;
&lt;h3 id=&#34;primecpp&#34;&gt;Prime.cpp&lt;/h3&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-cpp&#34; data-lang=&#34;cpp&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#include&lt;/span&gt; &lt;span style=&#34;color:#6e738d;font-weight:bold;font-style:italic&#34;&gt;&amp;#34;PrimeLib.hpp&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#include&lt;/span&gt; &lt;span style=&#34;color:#6e738d;font-weight:bold;font-style:italic&#34;&gt;&amp;lt;iostream&amp;gt;&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;using&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;namespace&lt;/span&gt; std;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;int&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;main&lt;/span&gt;(&lt;span style=&#34;color:#ed8796&#34;&gt;int&lt;/span&gt; argc, &lt;span style=&#34;color:#ed8796&#34;&gt;char&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;*&lt;/span&gt;argv[]) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; (argc &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;==&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;1&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        cout &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;lt;&amp;lt;&lt;/span&gt; random_prime() &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34; &amp;#34;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    } &lt;span style=&#34;color:#c6a0f6&#34;&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;for&lt;/span&gt; (&lt;span style=&#34;color:#ed8796&#34;&gt;int&lt;/span&gt; i &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;1&lt;/span&gt;; i &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;lt;=&lt;/span&gt; argc &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;-&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;1&lt;/span&gt;; i&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;++&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//in a real program would want to handle error
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;const&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;long&lt;/span&gt; num &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; std&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;::&lt;/span&gt;stoi(argv[i]);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            cout &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;lt;&amp;lt;&lt;/span&gt; prime_at(num) &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34; &amp;#34;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    cout &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;lt;&amp;lt;&lt;/span&gt; endl;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;0&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;primelibhpp&#34;&gt;PrimeLib.hpp&lt;/h3&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-cpp&#34; data-lang=&#34;cpp&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#ifndef PRIME_INCLUDED
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#define PRIME_INCLUDED
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//prime in first 10000 primes at index
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;int&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;prime_at&lt;/span&gt;(&lt;span style=&#34;color:#ed8796&#34;&gt;int&lt;/span&gt; index);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//random prime within first 10000 primes
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;int&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;random_prime&lt;/span&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#endif
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;primelibcpp&#34;&gt;PrimeLib.cpp&lt;/h3&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-cpp&#34; data-lang=&#34;cpp&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#include&lt;/span&gt; &lt;span style=&#34;color:#6e738d;font-weight:bold;font-style:italic&#34;&gt;&amp;#34;PrimeLib.hpp&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#include&lt;/span&gt; &lt;span style=&#34;color:#6e738d;font-weight:bold;font-style:italic&#34;&gt;&amp;lt;fstream&amp;gt;&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#include&lt;/span&gt; &lt;span style=&#34;color:#6e738d;font-weight:bold;font-style:italic&#34;&gt;&amp;lt;random&amp;gt;&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#include&lt;/span&gt; &lt;span style=&#34;color:#6e738d;font-weight:bold;font-style:italic&#34;&gt;&amp;lt;string&amp;gt;&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// Max line is 12 characters long
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;const&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;int&lt;/span&gt; max_line_length &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;16&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// 10,000th prime is 104729
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;const&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;int&lt;/span&gt; max_prime_length &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;6&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;int&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;readNthLine&lt;/span&gt;(std&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;::&lt;/span&gt;ifstream &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;amp;&lt;/span&gt;in, &lt;span style=&#34;color:#ed8796&#34;&gt;int&lt;/span&gt; index) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;for&lt;/span&gt; (&lt;span style=&#34;color:#ed8796&#34;&gt;int&lt;/span&gt; i &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;0&lt;/span&gt;; i &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;lt;&lt;/span&gt; index &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;-&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;1&lt;/span&gt;; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;++&lt;/span&gt;i) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// if don&amp;#39;t know max line length
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//  in.ignore(std::numeric_limits&amp;lt;std::streamsize&amp;gt;::max(), &amp;#39;\n&amp;#39;);
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;        in.ignore(max_line_length, &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#39;\n&amp;#39;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// What about a char *p instead of string?
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// Why/Why not do that in &amp;#34;Modern C++&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;    std&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;::&lt;/span&gt;string s;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    s.reserve(max_prime_length);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    std&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;::&lt;/span&gt;getline(in.ignore(max_line_length, &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#39; &amp;#39;&lt;/span&gt;), s);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; std&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;::&lt;/span&gt;stoi(s);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;};
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// just because.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// https://stackoverflow.com/questions/5008804/generating-a-random-integer-from-a-range
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;template&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;typename&lt;/span&gt; T&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;gt;&lt;/span&gt; T fancy_random(&lt;span style=&#34;color:#c6a0f6&#34;&gt;const&lt;/span&gt; T &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;amp;&lt;/span&gt;min, &lt;span style=&#34;color:#c6a0f6&#34;&gt;const&lt;/span&gt; T &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;amp;&lt;/span&gt;max) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    std&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;::&lt;/span&gt;random_device seed_maker;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    std&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;::&lt;/span&gt;mt19937 generator(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        seed_maker()); &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// Random-number engine to use (Mersenne-Twister)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;    std&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;::&lt;/span&gt;uniform_int_distribution&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;lt;&lt;/span&gt;T&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;gt;&lt;/span&gt; distribution(min,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                                                  max); &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// Guaranteed unbiased
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;distribution&lt;/span&gt;(generator);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// random prime within first 10000 primes
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;int&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;random_prime&lt;/span&gt;() { &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; prime_at(fancy_random(&lt;span style=&#34;color:#f5a97f&#34;&gt;0&lt;/span&gt;, &lt;span style=&#34;color:#f5a97f&#34;&gt;10000&lt;/span&gt;)); }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// prime in first 10000 primes at index
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;int&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;prime_at&lt;/span&gt;(&lt;span style=&#34;color:#ed8796&#34;&gt;int&lt;/span&gt; index) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    std&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;::&lt;/span&gt;ifstream primesFile(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;resources/b000040.txt&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; (primesFile.is_open()) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; readNthLine(primesFile, index);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    } &lt;span style=&#34;color:#c6a0f6&#34;&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// handle error
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;-&lt;/span&gt;&lt;span style=&#34;color:#f5a97f&#34;&gt;1&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;prime-numbers-text&#34;&gt;Prime Numbers text&lt;/h3&gt;
&lt;p&gt;The supplied &lt;a href=&#34;https://oeis.org/A000040&#34;&gt;prime numbers&lt;/a&gt; file has the prime&amp;rsquo;s index number followed by the prime itself. From the  &lt;a href=&#34;https://oeis.org&#34;&gt;The On-Line Encyclopedia of Integer Sequences&lt;/a&gt;&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-txt&#34; data-lang=&#34;txt&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;249 1579
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;250 1583
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;251 1597
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;252 1601
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;253 1607
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;254 1609
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;255 1613
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;256 1619
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description>
    </item>
    
    
    
    <item>
      <title>Hello C&#43;&#43; my old friend.</title>
      <link>https://whynotestflight.com/excuses/hello-c-my-old-friend./</link>
      <pubDate>Mon, 07 Aug 2023 00:00:00 +0000</pubDate>
      
      <guid>https://whynotestflight.com/excuses/hello-c-my-old-friend./</guid>
      <description>&lt;p&gt;It&amp;rsquo;s &lt;a href=&#34;https://github.com/carlynorama/Arduino-Library-Button&#34;&gt;been a minute&lt;/a&gt; since I spent real quality time with C++, so it&amp;rsquo;s time to do a refresher. Even then I was writing C++ for embedded systems, an entirely different beast than working with it for something like a desktop or iOS app. I plan to follow the same pattern I did with my recent C brush up.&lt;/p&gt;
&lt;p&gt;For that I wrote:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A small pure C project to get familiar with the modern tools on a Mac
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://whynotestflight.com/excuses/so-what-if-i-wanted-to-write-some-c-with-no-swift/&#34;&gt;related post&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/carlynorama/Hello_C_using_VScode&#34;&gt;https://github.com/carlynorama/Hello_C_using_VScode&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;A Swift project that has C files mixed in
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://whynotestflight.com/excuses/but-some-of-my-best-friends-are-c/&#34;&gt;related post&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/carlynorama/DirectIncludeC/&#34;&gt;https://github.com/carlynorama/DirectIncludeC/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;A library where Swift Target Wraps C Target &amp;amp; a test project
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://whynotestflight.com/excuses/uh-oh-were-going-unsafe/&#34;&gt;related post&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/carlynorama/UnsafeWrapCSampler&#34;&gt;https://github.com/carlynorama/UnsafeWrapCSampler&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/carlynorama/UnsafeExplorer&#34;&gt;https://github.com/carlynorama/UnsafeExplorer&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;A Swift library that wraps a system installed C library &amp;amp; test project
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://whynotestflight.com/excuses/can-i-get-my-hands-on-a-homebrew-installed-library/&#34;&gt;related post&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/carlynorama/SwiftLIBPNG&#34;&gt;https://github.com/carlynorama/SwiftLIBPNG&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/carlynorama/clipng&#34;&gt;https://github.com/carlynorama/clipng&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;My original intention, to use OpenUSD as the libpng analog, has been blown out of the water by how crazy extensive and way more than a file format OpenUSD is. I will likely pick something simpler for my Swift/C++ Interop Hello World, especially since that&amp;rsquo;s so new too. TBD what it will be.&lt;/p&gt;
&lt;p&gt;In the mean time let&amp;rsquo;s get started with a little C++ scratch-pad project.&lt;/p&gt;
&lt;p&gt;REPO: &lt;a href=&#34;https://github.com/carlynorama/Hello_Cpp_Using_VSCode&#34;&gt;https://github.com/carlynorama/Hello_Cpp_Using_VSCode&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&#34;c-project-start-up&#34;&gt;C++ Project Start Up&lt;/h2&gt;
&lt;h3 id=&#34;check-the-environment&#34;&gt;Check the Environment&lt;/h3&gt;
&lt;p&gt;C++ needs a compiler. Confirm what tools are available. My result on checking:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-zsh&#34; data-lang=&#34;zsh&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;clang --version     &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# Apple clang version 14.0.3 (clang-1403.0.22.14.1)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;gcc --version       &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# aliases clang&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;g++ --version       &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# also aliases clang&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;cmake --version     &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# cmake version 3.27.1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;make --version      &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# GNU Make 3.81&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;set-up-project&#34;&gt;Set Up Project&lt;/h3&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-zsh&#34; data-lang=&#34;zsh&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;mkdir &lt;span style=&#34;color:#f4dbd6&#34;&gt;$PROJECT_NAME&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#91d7e3&#34;&gt;cd&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;$PROJECT_NAME&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;git init
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;touch .gitignore
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;touch HelloWorld.cpp
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h4 id=&#34;gitignore&#34;&gt;gitignore&lt;/h4&gt;
&lt;p&gt;GitHub &lt;a href=&#34;https://github.com/github/gitignore/blob/main/C%2B%2B.gitignore&#34;&gt;provides more&lt;/a&gt;, but bare minium:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;.DS_Store
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;HelloWorld &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# Leave out build of default script&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# Will eventually put all binaries in a bin folder&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;bin/
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;*.out &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#in case forget to add a -o flag to compiler call&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## Apple for iOS&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## can turn them off by not using -g in compiler call&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## or using -g0 compiler flag&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;*.dSYM
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h4 id=&#34;helloworldcpp&#34;&gt;HelloWorld.cpp&lt;/h4&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-cpp&#34; data-lang=&#34;cpp&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#include&lt;/span&gt; &lt;span style=&#34;color:#6e738d;font-weight:bold;font-style:italic&#34;&gt;&amp;lt;iostream&amp;gt;&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;int&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;main&lt;/span&gt;()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    std&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;::&lt;/span&gt;cout &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Hello World&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;lt;&amp;lt;&lt;/span&gt; std&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;::&lt;/span&gt;endl;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-zsh&#34; data-lang=&#34;zsh&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# -o for output file name, &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# if none provided will be a.out https://en.wikipedia.org/wiki/A.out&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;g++ HelloWorld.cpp -o HelloWorld
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;./HelloWorld
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;set-up-vscode&#34;&gt;Set Up VSCode&lt;/h3&gt;
&lt;h4 id=&#34;compile-options&#34;&gt;Compile Options&lt;/h4&gt;
&lt;p&gt;With a .cpp file open, hit the run button on the top right to &lt;a href=&#34;https://code.visualstudio.com/docs/cpp/config-clang-mac&#34;&gt;link clang up to VSCode&lt;/a&gt;. A &lt;code&gt;tasks.json&lt;/code&gt; file will be generated. The below is an example of tha file after choosing &lt;code&gt;clang++ build active file&lt;/code&gt;, with some noted changes.&lt;/p&gt;
&lt;p&gt;For more on available arguments:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://clang.llvm.org/docs/ClangCommandLineReference.html&#34;&gt;https://clang.llvm.org/docs/ClangCommandLineReference.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://clang.llvm.org/get_started.html&#34;&gt;https://clang.llvm.org/get_started.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://gcc.gnu.org/onlinedocs/gcc/&#34;&gt;https://gcc.gnu.org/onlinedocs/gcc/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;C++ status: &lt;a href=&#34;https://clang.llvm.org/cxx_status.html&#34;&gt;https://clang.llvm.org/cxx_status.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;on dSYM files: &lt;a href=&#34;https://developer.apple.com/videos/play/wwdc2021/10211/&#34;&gt;https://developer.apple.com/videos/play/wwdc2021/10211/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;tasksjson&#34;&gt;tasks.json&lt;/h3&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-json&#34; data-lang=&#34;json&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;&amp;#34;tasks&amp;#34;&lt;/span&gt;: [
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;&amp;#34;type&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;cppbuild&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;&amp;#34;label&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;C/C++: clang++ build active file&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;&amp;#34;command&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;/usr/bin/clang++&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;&amp;#34;args&amp;#34;&lt;/span&gt;: [
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;-fcolor-diagnostics&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;-fansi-escape-codes&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//ADDED!
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;                &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;-std=c++17&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//-g is default, -g0 turns off the creation of .dSYM files
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;                &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;-g0&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;${file}&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;-o&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//default: ${fileDirname}/${fileBasenameNoExtension}
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;                &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;${workspaceFolder}/bin/${fileBasenameNoExtension}&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            ],
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;&amp;#34;options&amp;#34;&lt;/span&gt;: {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#c6a0f6&#34;&gt;&amp;#34;cwd&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;${fileDirname}&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            },
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;&amp;#34;problemMatcher&amp;#34;&lt;/span&gt;: [
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;$gcc&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            ],
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;&amp;#34;group&amp;#34;&lt;/span&gt;: {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#c6a0f6&#34;&gt;&amp;#34;kind&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;build&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#c6a0f6&#34;&gt;&amp;#34;isDefault&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#f5a97f&#34;&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            },
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;&amp;#34;detail&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Task generated by Debugger.&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    ],
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;&amp;#34;version&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;2.0.0&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;It&amp;rsquo;s possible to use a later library via a command line compile, too:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-zsh&#34; data-lang=&#34;zsh&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;g++ HelloWorld.cpp -std&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt;c++17 -o HelloWorld
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;./HelloWorld
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h4 id=&#34;formatting-options&#34;&gt;Formatting Options&lt;/h4&gt;
&lt;p&gt;VSCode&amp;rsquo;s default style is to put the opening curly brace below the starting line, but this is &lt;a href=&#34;https://stackoverflow.com/questions/46111834/format-curly-braces-on-same-line-in-c-vscode&#34;&gt;easily changed&lt;/a&gt; by adding the following line to the workspace&amp;rsquo;s &lt;code&gt;.vscode/settings.json&lt;/code&gt;&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-json&#34; data-lang=&#34;json&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{ 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//other settings...,
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;&amp;#34;C_Cpp.clang_format_fallbackStyle&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;LLVM&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;To be fancier provide a &lt;code&gt;.clang-format&lt;/code&gt; file in the project&amp;rsquo;s root directory. An added benefit, a &lt;code&gt;.clang-format&lt;/code&gt; file will be usable by others not using VSCode.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-yaml&#34; data-lang=&#34;yaml&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f5a97f&#34;&gt;---&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;Language&lt;/span&gt;:    	Cpp
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# BasedOnStyle:  LLVM&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;AccessModifierOffset&lt;/span&gt;: -&lt;span style=&#34;color:#f5a97f&#34;&gt;4&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;IndentWidth&lt;/span&gt;: &lt;span style=&#34;color:#f5a97f&#34;&gt;4&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;TabWidth&lt;/span&gt;: &lt;span style=&#34;color:#f5a97f&#34;&gt;4&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;AlignAfterOpenBracket&lt;/span&gt;: Align
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;AlignConsecutiveMacros&lt;/span&gt;: &lt;span style=&#34;color:#f5a97f&#34;&gt;false&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;AlignConsecutiveAssignments&lt;/span&gt;: &lt;span style=&#34;color:#f5a97f&#34;&gt;false&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://code.visualstudio.com/docs/cpp/cpp-ide#_code-formatting&#34;&gt;https://code.visualstudio.com/docs/cpp/cpp-ide#_code-formatting&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://clang.llvm.org/docs/ClangFormat.html&#34;&gt;https://clang.llvm.org/docs/ClangFormat.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://www.clangpowertools.com/blog/getting-started-with-clang-format-style-options.html&#34;&gt;https://www.clangpowertools.com/blog/getting-started-with-clang-format-style-options.html&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;c-review&#34;&gt;C++ Review&lt;/h2&gt;
&lt;h3 id=&#34;resources&#34;&gt;Resources&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Standard Library headers: &lt;a href=&#34;https://en.cppreference.com/w/cpp/header&#34;&gt;https://en.cppreference.com/w/cpp/header&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;keywords: &lt;a href=&#34;https://en.cppreference.com/w/cpp/keyword&#34;&gt;https://en.cppreference.com/w/cpp/keyword&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Precedence rules: &lt;a href=&#34;https://en.cppreference.com/w/cpp/language/operator_precedence&#34;&gt;https://en.cppreference.com/w/cpp/language/operator_precedence&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://cplusplus.com/reference/&#34;&gt;https://cplusplus.com/reference/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Easy clear course to blow through, down side, requires (free) account: &lt;a href=&#34;https://www.codecademy.com/courses/c-plus-plus-for-programmers/&#34;&gt;https://www.codecademy.com/courses/c-plus-plus-for-programmers/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Also when back and looked at a &lt;a href=&#34;https://github.com/SketchingInHardware/skommunity&#34;&gt;2021 project&lt;/a&gt; to remind myself about Templates. Originally cribbed from &lt;a href=&#34;https://github.com/FastLED/FastLED&#34;&gt;FastLED&lt;/a&gt; a really well written hardware library.&lt;/p&gt;
&lt;h3 id=&#34;practice-code&#34;&gt;Practice Code&lt;/h3&gt;
&lt;p&gt;Each file can be compiled and run independently.&lt;/p&gt;
&lt;h4 id=&#34;helloworldcpp-1&#34;&gt;HelloWorld.cpp&lt;/h4&gt;
&lt;p&gt;Miscellaneous things to remember about C++&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-cpp&#34; data-lang=&#34;cpp&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// Preprocessor Directive
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// Standard library names in &amp;lt; &amp;gt;,
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// User-defined library names in &amp;#34; &amp;#34;.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#include&lt;/span&gt; &lt;span style=&#34;color:#6e738d;font-weight:bold;font-style:italic&#34;&gt;&amp;lt;iostream&amp;gt;&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;using&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;namespace&lt;/span&gt; std; &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//To drop the std:: everywhere. 
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// No header, no hoisting. Functions/vars used in main() need to be declared
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// above main in a single-file program.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// declare a constant
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;const&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;int&lt;/span&gt; number &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;3&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// function with no return
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;void&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;whisperToProgrammer&lt;/span&gt;() { cout &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Shhh, I&amp;#39;m telling you secretly&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;lt;&amp;lt;&lt;/span&gt; endl; }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// function with string return and int parameter with a default value
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;string &lt;span style=&#34;color:#8aadf4&#34;&gt;shareTheMessageWithTheClass&lt;/span&gt;(&lt;span style=&#34;color:#ed8796&#34;&gt;int&lt;/span&gt; count &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;10&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    string message &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;LA&amp;#34;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;for&lt;/span&gt; (&lt;span style=&#34;color:#ed8796&#34;&gt;int&lt;/span&gt; i &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;1&lt;/span&gt;; i &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;lt;&lt;/span&gt; count; i&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;++&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        message.append(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34; LA&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; message;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// pass in a reference
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;void&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;setMeTo5&lt;/span&gt;(&lt;span style=&#34;color:#ed8796&#34;&gt;int&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;amp;&lt;/span&gt;numToChange) { numToChange &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;5&lt;/span&gt;; }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// Note on function declarations:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// Return types not used to tell overloads apart.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//--------------------------------------------------------------------- main()
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// friendly neighborhood main function
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;int&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;main&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;int&lt;/span&gt; changeable &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;3&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;int&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;amp;&lt;/span&gt;alias &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; changeable;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    changeable &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;+=&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;3&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// if had not included namespace line.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// std::cout &amp;lt;&amp;lt; &amp;#34;Hello, World!&amp;#34; &amp;lt;&amp;lt; std::endl;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;    cout &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Hello, World! &amp;#34;&lt;/span&gt;; &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//&amp;lt;-- no end of line, it&amp;#39;s not automatic.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// has returns. alias should == 6
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;    cout &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;I&amp;#39;m so happy to see you.&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\n&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;Here are &amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;lt;&amp;lt;&lt;/span&gt; alias &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34; fish.&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;lt;&amp;lt;&lt;/span&gt; endl;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// should be the memory pointers in hex, and they should be the same.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;    cout &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;amp;&lt;/span&gt;alias &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#39; &amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;amp;&lt;/span&gt;changeable &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;lt;&amp;lt;&lt;/span&gt; endl;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// Don&amp;#39;t forget in C++ case statements fall through by default.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;switch&lt;/span&gt; (changeable) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;case&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;6&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        cout &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Everything as expected.&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\n&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;break&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// And switches do NOT have to be exhaustive.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//  default:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//      cout &amp;lt;&amp;lt; &amp;#34;Something feels hinky.\n&amp;#34;;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//      break;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// Home sweet for loop home.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;for&lt;/span&gt; (&lt;span style=&#34;color:#ed8796&#34;&gt;int&lt;/span&gt; i &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;1&lt;/span&gt;; i &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;lt;=&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;5&lt;/span&gt;; i&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;++&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        cout &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;lt;&amp;lt;&lt;/span&gt; i;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    cout &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;lt;&amp;lt;&lt;/span&gt; endl;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// foreach
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// warning: range-based for loop is a C++11 extension
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// warning: &amp;#39;auto&amp;#39; type specifier is a C++11 extension
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// to compile: g++ HelloWorld.cpp -std=c++17 -o HelloWorld
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;int&lt;/span&gt; pi_times_100k[&lt;span style=&#34;color:#f5a97f&#34;&gt;6&lt;/span&gt;] &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; {&lt;span style=&#34;color:#f5a97f&#34;&gt;3&lt;/span&gt;, &lt;span style=&#34;color:#f5a97f&#34;&gt;1&lt;/span&gt;, &lt;span style=&#34;color:#f5a97f&#34;&gt;4&lt;/span&gt;, &lt;span style=&#34;color:#f5a97f&#34;&gt;1&lt;/span&gt;, &lt;span style=&#34;color:#f5a97f&#34;&gt;5&lt;/span&gt;, &lt;span style=&#34;color:#f5a97f&#34;&gt;9&lt;/span&gt;};
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// for (int number : pi_times_100k) {
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;for&lt;/span&gt; (&lt;span style=&#34;color:#c6a0f6&#34;&gt;auto&lt;/span&gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;number&lt;/span&gt; : pi_times_100k) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        cout &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;lt;&amp;lt;&lt;/span&gt; number;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    cout &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;lt;&amp;lt;&lt;/span&gt; endl;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    whisperToProgrammer();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    setMeTo5(changeable);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// Should print out 5 LA&amp;#39;s
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;    cout &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;lt;&amp;lt;&lt;/span&gt; shareTheMessageWithTheClass(alias) &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;lt;&amp;lt;&lt;/span&gt; endl;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// sometimes left out, but is the everything is okay line
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;0&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h4 id=&#34;classescpp&#34;&gt;Classes.cpp&lt;/h4&gt;
&lt;p&gt;Example classes, with inheritance&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-cpp&#34; data-lang=&#34;cpp&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#include&lt;/span&gt; &lt;span style=&#34;color:#6e738d;font-weight:bold;font-style:italic&#34;&gt;&amp;lt;iostream&amp;gt;&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;Banner&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// variables are by default private.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// Can set them pubic or make public mutator functions.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;public&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    std&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;::&lt;/span&gt;string message;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;void&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;wave&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        std&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;::&lt;/span&gt;cout
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;********************************************************&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\n&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        std&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;::&lt;/span&gt;cout &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;lt;&amp;lt;&lt;/span&gt; message &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\n&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        std&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;::&lt;/span&gt;cout
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;********************************************************&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\n&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// example of declaring method without implementing it, i.e. for header
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// files.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;void&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;outside&lt;/span&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;};
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;void&lt;/span&gt; Banner&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;::&lt;/span&gt;outside() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    std&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;::&lt;/span&gt;cout &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;++++++++++++++++++++++++++++++++++++++++++++++++++++++++&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\n&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;};
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// https://en.cppreference.com/w/cpp/language/derived_class
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// https://learn.microsoft.com/en-us/cpp/cpp/member-access-control-cpp
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;HasDefaults&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;protected&lt;/span&gt; Banner {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;public&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    HasDefaults(std&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;::&lt;/span&gt;string say_this &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;This is my standard message!&amp;#34;&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        message &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; say_this;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// base class is protected, but can be accessed via mutator functions.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;void&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;update&lt;/span&gt;(std&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;::&lt;/span&gt;string new_message) { message &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; new_message; }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// Allows access to protected base class function, but is not an override
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;void&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;passThrough&lt;/span&gt;() { wave(); }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// Destructor
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;~&lt;/span&gt;HasDefaults() { std&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;::&lt;/span&gt;cout &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Nothing more to do&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\n&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;; }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;};
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// Third time a charm
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;WrapAgain&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;public&lt;/span&gt; HasDefaults {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;public&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// Treats parent initializer as member initializer list.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;    WrapAgain(std&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;::&lt;/span&gt;string real_message) &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;:&lt;/span&gt; HasDefaults(real_message) {}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// no override keyword (keyword: polymorphism)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;void&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;passThrough&lt;/span&gt;() { std&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;::&lt;/span&gt;cout &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;+++++&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;lt;&amp;lt;&lt;/span&gt; message &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;+++++&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\n&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;; }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;};
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// A class with constants needs to have &amp;#34;member initializer list&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// https://en.cppreference.com/w/cpp/language/constructor
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;HousePlant&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;private&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;const&lt;/span&gt; std&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;::&lt;/span&gt;string genus;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;const&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;int&lt;/span&gt; year_acquired;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;public&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    HousePlant() &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;:&lt;/span&gt; genus(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Crassula&amp;#34;&lt;/span&gt;), year_acquired(&lt;span style=&#34;color:#f5a97f&#34;&gt;2004&lt;/span&gt;) {}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;};
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//----------------------------------------------------------------------- main()
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;int&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;main&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    Banner end_of_message;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    end_of_message.message &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Thats all they wrote!&amp;#34;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    end_of_message.wave();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    end_of_message.outside();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    HasDefaults example;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    example.passThrough();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    example.update(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;But I can say something new!&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    example.passThrough();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    WrapAgain slimmessage(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;keep it clean&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    slimmessage.passThrough();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;0&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h4 id=&#34;containerscpp&#34;&gt;Containers.cpp&lt;/h4&gt;
&lt;p&gt;Various data types like, arrays, vectors, stacks, queues, sets and maps.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-cpp&#34; data-lang=&#34;cpp&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#include&lt;/span&gt; &lt;span style=&#34;color:#6e738d;font-weight:bold;font-style:italic&#34;&gt;&amp;lt;iostream&amp;gt;&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#include&lt;/span&gt; &lt;span style=&#34;color:#6e738d;font-weight:bold;font-style:italic&#34;&gt;&amp;lt;map&amp;gt;&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#include&lt;/span&gt; &lt;span style=&#34;color:#6e738d;font-weight:bold;font-style:italic&#34;&gt;&amp;lt;queue&amp;gt;&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#include&lt;/span&gt; &lt;span style=&#34;color:#6e738d;font-weight:bold;font-style:italic&#34;&gt;&amp;lt;set&amp;gt;&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#include&lt;/span&gt; &lt;span style=&#34;color:#6e738d;font-weight:bold;font-style:italic&#34;&gt;&amp;lt;stack&amp;gt;&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#include&lt;/span&gt; &lt;span style=&#34;color:#6e738d;font-weight:bold;font-style:italic&#34;&gt;&amp;lt;unordered_map&amp;gt;&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#include&lt;/span&gt; &lt;span style=&#34;color:#6e738d;font-weight:bold;font-style:italic&#34;&gt;&amp;lt;unordered_set&amp;gt;&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#include&lt;/span&gt; &lt;span style=&#34;color:#6e738d;font-weight:bold;font-style:italic&#34;&gt;&amp;lt;vector&amp;gt;&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// https://cplusplus.com/reference/stl/
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// -------------------------------------------------------------- Arrays
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// https://cplusplus.com/reference/array/array/
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// fixed sized
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// int count_down[] = { 10, 9, 8, 7, 6, 5, 4, 3, 2, 1 };
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;const&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;int&lt;/span&gt; row_count &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;2&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;const&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;int&lt;/span&gt; col_count &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;3&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;int&lt;/span&gt; grid[row_count][col_count] &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    {&lt;span style=&#34;color:#f5a97f&#34;&gt;0&lt;/span&gt;, &lt;span style=&#34;color:#f5a97f&#34;&gt;1&lt;/span&gt;, &lt;span style=&#34;color:#f5a97f&#34;&gt;2&lt;/span&gt;},
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    {&lt;span style=&#34;color:#f5a97f&#34;&gt;3&lt;/span&gt;, &lt;span style=&#34;color:#f5a97f&#34;&gt;4&lt;/span&gt;, &lt;span style=&#34;color:#f5a97f&#34;&gt;5&lt;/span&gt;},
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;};
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;const&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;int&lt;/span&gt; depth_count &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;4&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;int&lt;/span&gt; cube[row_count][col_count][depth_count] &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    {{&lt;span style=&#34;color:#f5a97f&#34;&gt;0&lt;/span&gt;, &lt;span style=&#34;color:#f5a97f&#34;&gt;1&lt;/span&gt;, &lt;span style=&#34;color:#f5a97f&#34;&gt;2&lt;/span&gt;, &lt;span style=&#34;color:#f5a97f&#34;&gt;3&lt;/span&gt;}, {&lt;span style=&#34;color:#f5a97f&#34;&gt;4&lt;/span&gt;, &lt;span style=&#34;color:#f5a97f&#34;&gt;5&lt;/span&gt;, &lt;span style=&#34;color:#f5a97f&#34;&gt;6&lt;/span&gt;, &lt;span style=&#34;color:#f5a97f&#34;&gt;7&lt;/span&gt;}, {&lt;span style=&#34;color:#f5a97f&#34;&gt;8&lt;/span&gt;, &lt;span style=&#34;color:#f5a97f&#34;&gt;9&lt;/span&gt;, &lt;span style=&#34;color:#f5a97f&#34;&gt;10&lt;/span&gt;, &lt;span style=&#34;color:#f5a97f&#34;&gt;11&lt;/span&gt;}},
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    {{&lt;span style=&#34;color:#f5a97f&#34;&gt;12&lt;/span&gt;, &lt;span style=&#34;color:#f5a97f&#34;&gt;13&lt;/span&gt;, &lt;span style=&#34;color:#f5a97f&#34;&gt;14&lt;/span&gt;, &lt;span style=&#34;color:#f5a97f&#34;&gt;15&lt;/span&gt;}, {&lt;span style=&#34;color:#f5a97f&#34;&gt;16&lt;/span&gt;, &lt;span style=&#34;color:#f5a97f&#34;&gt;17&lt;/span&gt;, &lt;span style=&#34;color:#f5a97f&#34;&gt;18&lt;/span&gt;, &lt;span style=&#34;color:#f5a97f&#34;&gt;19&lt;/span&gt;}, {&lt;span style=&#34;color:#f5a97f&#34;&gt;20&lt;/span&gt;, &lt;span style=&#34;color:#f5a97f&#34;&gt;21&lt;/span&gt;, &lt;span style=&#34;color:#f5a97f&#34;&gt;22&lt;/span&gt;, &lt;span style=&#34;color:#f5a97f&#34;&gt;23&lt;/span&gt;}},
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;};
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// -------------------------------------------------------------- Vectors
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// https://cplusplus.com/reference/vector/vector/
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// Variable sized array
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;std&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;::&lt;/span&gt;vector&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;char&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;gt;&lt;/span&gt; alphabet &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; {&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#39;a&amp;#39;&lt;/span&gt;, &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#39;b&amp;#39;&lt;/span&gt;, &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#39;c&amp;#39;&lt;/span&gt;};
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// -------------------------------------------------------------- Stacks
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// https://cplusplus.com/reference/stack/stack/
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// LIFO
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;std&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;::&lt;/span&gt;stack&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;int&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;gt;&lt;/span&gt; plates;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// -------------------------------------------------------------- Queue
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// https://cplusplus.com/reference/queue/queue/
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// FIFO
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;std&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;::&lt;/span&gt;queue&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;lt;&lt;/span&gt;std&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;::&lt;/span&gt;string&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;gt;&lt;/span&gt; line;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// -------------------------------------------------------------- Set
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// https://cplusplus.com/reference/set/set/
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// https://cplusplus.com/reference/unordered_set/unordered_set/
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;std&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;::&lt;/span&gt;unordered_set&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;int&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;gt;&lt;/span&gt; primes({&lt;span style=&#34;color:#f5a97f&#34;&gt;2&lt;/span&gt;, &lt;span style=&#34;color:#f5a97f&#34;&gt;3&lt;/span&gt;, &lt;span style=&#34;color:#f5a97f&#34;&gt;5&lt;/span&gt;, &lt;span style=&#34;color:#f5a97f&#34;&gt;7&lt;/span&gt;});
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;void&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;removeAndPrint&lt;/span&gt;(&lt;span style=&#34;color:#ed8796&#34;&gt;int&lt;/span&gt; to_remove, std&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;::&lt;/span&gt;unordered_set&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;int&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;amp;&lt;/span&gt;from_this) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#ed8796&#34;&gt;int&lt;/span&gt; result &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; from_this.erase(to_remove);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; (result &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;==&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;1&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    std&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;::&lt;/span&gt;cout &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;removed a &amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;lt;&amp;lt;&lt;/span&gt; to_remove &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\n&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  } &lt;span style=&#34;color:#c6a0f6&#34;&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    std&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;::&lt;/span&gt;cout &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;there wasn&amp;#39;t a &amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;lt;&amp;lt;&lt;/span&gt; to_remove &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\n&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;bool&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;contains&lt;/span&gt;(&lt;span style=&#34;color:#ed8796&#34;&gt;int&lt;/span&gt; to_find, &lt;span style=&#34;color:#c6a0f6&#34;&gt;const&lt;/span&gt; std&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;::&lt;/span&gt;unordered_set&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;int&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;amp;&lt;/span&gt;in_this) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#ed8796&#34;&gt;int&lt;/span&gt; result &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; in_this.count(to_find);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; (result &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;!=&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;0&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    std&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;::&lt;/span&gt;cout &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;found a &amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;lt;&amp;lt;&lt;/span&gt; to_find &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\n&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;true&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  } &lt;span style=&#34;color:#c6a0f6&#34;&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    std&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;::&lt;/span&gt;cout &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;there wasn&amp;#39;t a &amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;lt;&amp;lt;&lt;/span&gt; to_find &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\n&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;false&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// -------------------------------------------------------------- Map
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// https://cplusplus.com/reference/unordered_map/
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// https://cplusplus.com/reference/map/
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// keys must be unique, but is hashed on BOTH key and value.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;std&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;::&lt;/span&gt;unordered_map&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;lt;&lt;/span&gt;std&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;::&lt;/span&gt;string, &lt;span style=&#34;color:#ed8796&#34;&gt;int&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;gt;&lt;/span&gt; shopping_list({{&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;apples&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#f5a97f&#34;&gt;5&lt;/span&gt;},
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                                                    {&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;eggs&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#f5a97f&#34;&gt;12&lt;/span&gt;}});
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//---------------------------------------------------------------------- main()
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;int&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;main&lt;/span&gt;(&lt;span style=&#34;color:#ed8796&#34;&gt;int&lt;/span&gt; argc, &lt;span style=&#34;color:#ed8796&#34;&gt;char&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;*&lt;/span&gt;argv[]) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// Danger, this does not error out if put in too many args
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// -------------------------------------------------------------- Arrays
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;  &lt;span style=&#34;color:#ed8796&#34;&gt;int&lt;/span&gt; test_count[&lt;span style=&#34;color:#f5a97f&#34;&gt;5&lt;/span&gt;];
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#c6a0f6&#34;&gt;for&lt;/span&gt; (&lt;span style=&#34;color:#ed8796&#34;&gt;int&lt;/span&gt; i &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;0&lt;/span&gt;; i &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;lt;&lt;/span&gt; argc; i&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;++&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    std&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;::&lt;/span&gt;cout &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;arg &amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;lt;&amp;lt;&lt;/span&gt; i &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;: &amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;lt;&amp;lt;&lt;/span&gt; argv[i] &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\n&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    test_count[i] &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; i; &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// should have a max of 5
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;    std&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;::&lt;/span&gt;cout &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;overflow test &amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;lt;&amp;lt;&lt;/span&gt; i &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;: &amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;lt;&amp;lt;&lt;/span&gt; test_count[i] &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\n&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  std&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;::&lt;/span&gt;cout &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;lt;&amp;lt;&lt;/span&gt; grid[&lt;span style=&#34;color:#f5a97f&#34;&gt;1&lt;/span&gt;][&lt;span style=&#34;color:#f5a97f&#34;&gt;2&lt;/span&gt;] &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\n&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#c6a0f6&#34;&gt;for&lt;/span&gt; (&lt;span style=&#34;color:#ed8796&#34;&gt;int&lt;/span&gt; i &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;0&lt;/span&gt;; i &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;lt;&lt;/span&gt; row_count; i&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;++&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;for&lt;/span&gt; (&lt;span style=&#34;color:#ed8796&#34;&gt;int&lt;/span&gt; j &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;0&lt;/span&gt;; j &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;lt;&lt;/span&gt; col_count; j&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;++&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#c6a0f6&#34;&gt;for&lt;/span&gt; (&lt;span style=&#34;color:#ed8796&#34;&gt;int&lt;/span&gt; k &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;0&lt;/span&gt;; k &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;lt;&lt;/span&gt; depth_count; k&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;++&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        std&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;::&lt;/span&gt;cout &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;lt;&amp;lt;&lt;/span&gt; cube[i][j][k] &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;, &amp;#34;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      std&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;::&lt;/span&gt;cout &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\n&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    std&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;::&lt;/span&gt;cout &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\n&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// -------------------------------------------------------------- Vector
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;  alphabet.push_back(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#39;d&amp;#39;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  alphabet.push_back(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#39;e&amp;#39;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#c6a0f6&#34;&gt;for&lt;/span&gt; (&lt;span style=&#34;color:#c6a0f6&#34;&gt;auto&lt;/span&gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;letter&lt;/span&gt; : alphabet) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    std&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;::&lt;/span&gt;cout &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;lt;&amp;lt;&lt;/span&gt; letter;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  std&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;::&lt;/span&gt;cout &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\n&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#ed8796&#34;&gt;char&lt;/span&gt; first &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; alphabet.front();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  std&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;::&lt;/span&gt;cout &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;lt;&amp;lt;&lt;/span&gt; first &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\n&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//actually has vs .capacity() which is allocated
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;  &lt;span style=&#34;color:#ed8796&#34;&gt;int&lt;/span&gt; size &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; alphabet.size(); 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  std&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;::&lt;/span&gt;cout &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;lt;&amp;lt;&lt;/span&gt; size &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\n&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#c6a0f6&#34;&gt;for&lt;/span&gt; (&lt;span style=&#34;color:#c6a0f6&#34;&gt;auto&lt;/span&gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;letter&lt;/span&gt; : alphabet) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    std&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;::&lt;/span&gt;cout &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;lt;&amp;lt;&lt;/span&gt; letter;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  std&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;::&lt;/span&gt;cout &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\n&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// -------------------------------------------------------------- Stack
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;  plates.push(&lt;span style=&#34;color:#f5a97f&#34;&gt;3&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  plates.push(&lt;span style=&#34;color:#f5a97f&#34;&gt;8&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  plates.push(&lt;span style=&#34;color:#f5a97f&#34;&gt;5&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#c6a0f6&#34;&gt;const&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;int&lt;/span&gt; current_size &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; plates.size();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#c6a0f6&#34;&gt;for&lt;/span&gt; (&lt;span style=&#34;color:#ed8796&#34;&gt;int&lt;/span&gt; i &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;0&lt;/span&gt;; i &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;lt;&lt;/span&gt; current_size; i&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;++&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;int&lt;/span&gt; next &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; plates.top();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    plates.pop();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    std&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;::&lt;/span&gt;cout &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;lt;&amp;lt;&lt;/span&gt; next &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#39; &amp;#39;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  std&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;::&lt;/span&gt;cout &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\n&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// -------------------------------------------------------------- Queue
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;  line.push(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;George&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  line.push(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Bonny&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  line.push(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Linda&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  line.push(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Dianne&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#c6a0f6&#34;&gt;const&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;int&lt;/span&gt; line_size &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; line.size();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#c6a0f6&#34;&gt;for&lt;/span&gt; (&lt;span style=&#34;color:#ed8796&#34;&gt;int&lt;/span&gt; i &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;0&lt;/span&gt;; i &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;lt;&lt;/span&gt; line_size; i&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;++&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    std&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;::&lt;/span&gt;string next &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; line.front();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    line.pop();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    std&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;::&lt;/span&gt;cout &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;lt;&amp;lt;&lt;/span&gt; next &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#39; &amp;#39;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  std&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;::&lt;/span&gt;cout &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\n&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// -------------------------------------------------------------- Set
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;  primes.insert(&lt;span style=&#34;color:#f5a97f&#34;&gt;2&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  primes.insert(&lt;span style=&#34;color:#f5a97f&#34;&gt;7&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  primes.insert(&lt;span style=&#34;color:#f5a97f&#34;&gt;43&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#c6a0f6&#34;&gt;for&lt;/span&gt; (&lt;span style=&#34;color:#c6a0f6&#34;&gt;auto&lt;/span&gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;num&lt;/span&gt; : primes) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    std&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;::&lt;/span&gt;cout &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;lt;&amp;lt;&lt;/span&gt; num &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34; &amp;#34;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  std&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;::&lt;/span&gt;cout &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\n&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  removeAndPrint(&lt;span style=&#34;color:#f5a97f&#34;&gt;2&lt;/span&gt;, primes);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#c6a0f6&#34;&gt;for&lt;/span&gt; (&lt;span style=&#34;color:#c6a0f6&#34;&gt;auto&lt;/span&gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;num&lt;/span&gt; : primes) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    std&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;::&lt;/span&gt;cout &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;lt;&amp;lt;&lt;/span&gt; num &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34; &amp;#34;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  removeAndPrint(&lt;span style=&#34;color:#f5a97f&#34;&gt;2&lt;/span&gt;, primes);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#ed8796&#34;&gt;bool&lt;/span&gt; result &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; contains(&lt;span style=&#34;color:#f5a97f&#34;&gt;5&lt;/span&gt;, primes);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  std&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;::&lt;/span&gt;cout &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;lt;&amp;lt;&lt;/span&gt; result &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\n&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  std&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;::&lt;/span&gt;cout &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\n&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  std&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;::&lt;/span&gt;set&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;int&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;gt;&lt;/span&gt; ordered({&lt;span style=&#34;color:#f5a97f&#34;&gt;4&lt;/span&gt;, &lt;span style=&#34;color:#f5a97f&#34;&gt;2&lt;/span&gt;, &lt;span style=&#34;color:#f5a97f&#34;&gt;7&lt;/span&gt;, &lt;span style=&#34;color:#f5a97f&#34;&gt;1&lt;/span&gt;, &lt;span style=&#34;color:#f5a97f&#34;&gt;3&lt;/span&gt;});
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  std&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;::&lt;/span&gt;cout &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;set: &amp;#34;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#c6a0f6&#34;&gt;for&lt;/span&gt; (&lt;span style=&#34;color:#ed8796&#34;&gt;int&lt;/span&gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;n&lt;/span&gt; : ordered) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    std&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;::&lt;/span&gt;cout &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;lt;&amp;lt;&lt;/span&gt; n &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34; &amp;#34;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// consider also my_set.rbegin() and my_set.rend()
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;  std&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;::&lt;/span&gt;set&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;int&lt;/span&gt;, std&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;::&lt;/span&gt;greater&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;int&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;gt;&amp;gt;&lt;/span&gt; descending{&lt;span style=&#34;color:#f5a97f&#34;&gt;4&lt;/span&gt;, &lt;span style=&#34;color:#f5a97f&#34;&gt;2&lt;/span&gt;, &lt;span style=&#34;color:#f5a97f&#34;&gt;7&lt;/span&gt;, &lt;span style=&#34;color:#f5a97f&#34;&gt;1&lt;/span&gt;, &lt;span style=&#34;color:#f5a97f&#34;&gt;3&lt;/span&gt;};
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  std&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;::&lt;/span&gt;cout &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;descending set: &amp;#34;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#c6a0f6&#34;&gt;for&lt;/span&gt; (&lt;span style=&#34;color:#ed8796&#34;&gt;int&lt;/span&gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;n&lt;/span&gt; : descending) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    std&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;::&lt;/span&gt;cout &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;lt;&amp;lt;&lt;/span&gt; n &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34; &amp;#34;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// -------------------------------------------------------------- Map
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;  std&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;::&lt;/span&gt;cout &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\n&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  shopping_list.insert({&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;acorn squash&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#f5a97f&#34;&gt;1&lt;/span&gt;});    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// does insert
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;  shopping_list.insert({&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;cashews, bag of&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#f5a97f&#34;&gt;1&lt;/span&gt;}); &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// does insert
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;  shopping_list.insert({&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;eggs&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#f5a97f&#34;&gt;24&lt;/span&gt;});           &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// does not update.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;  shopping_list[&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;eggs&amp;#34;&lt;/span&gt;] &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f5a97f&#34;&gt;2&lt;/span&gt;; &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// does update, but will also create if does not exits.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;  &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// shopping_list.at(&amp;#34;frozen peas&amp;#34;); //will be error, out of range.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;  &lt;span style=&#34;color:#c6a0f6&#34;&gt;for&lt;/span&gt; (&lt;span style=&#34;color:#c6a0f6&#34;&gt;auto&lt;/span&gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;item&lt;/span&gt; : shopping_list) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    std&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;::&lt;/span&gt;cout &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;lt;&amp;lt;&lt;/span&gt; item.first &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34; &amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;lt;&amp;lt;&lt;/span&gt; item.second &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\n&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  shopping_list.insert_or_assign(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;apples&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#f5a97f&#34;&gt;3&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// shopping_list.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;  &lt;span style=&#34;color:#c6a0f6&#34;&gt;for&lt;/span&gt; (&lt;span style=&#34;color:#c6a0f6&#34;&gt;auto&lt;/span&gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;item&lt;/span&gt; : shopping_list) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    std&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;::&lt;/span&gt;cout &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;lt;&amp;lt;&lt;/span&gt; item.first &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34; &amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;lt;&amp;lt;&lt;/span&gt; item.second &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\n&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// erase and count work similarly to set, i.e. they return 1 if successful.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description>
    </item>
    
    
    
    <item>
      <title>Hello USD - Part 22: The Control Flow is a lie.</title>
      <link>https://whynotestflight.com/excuses/hello-usd-part-22-the-control-flow-is-a-lie./</link>
      <pubDate>Sat, 05 Aug 2023 00:00:00 +0000</pubDate>
      
      <guid>https://whynotestflight.com/excuses/hello-usd-part-22-the-control-flow-is-a-lie./</guid>
      <description>&lt;script type=&#39;text/javascript&#39; src=&#39;https://www.x3dom.org/download/x3dom.js&#39;&gt; &lt;/script&gt; 
&lt;p&gt;Continued from &lt;a href=&#34;https://whynotestflight.com/excuses/hello-usd-part-21-what-if-i-refactored-sketchpad-to-work-like-swiftui/&#34;&gt;last post&lt;/a&gt;, a fleshed out protocol based result builder now drives &lt;a href=&#34;https://github.com/carlynorama/SketchPad/tree/main/Sources/SketchPad&#34;&gt;SketchPad&lt;/a&gt;! It took some ironing out to get full parity with the &lt;code&gt;[Sphere]&lt;/code&gt; based one, especially the for loops. I&amp;rsquo;m happy as the new code puts me in good shape to add new features, but I don&amp;rsquo;t love it yet.&lt;/p&gt;
&lt;p&gt;The &lt;a href=&#34;https://github.com/apple/swift-evolution/blob/main/proposals/0289-result-builders.md&#34;&gt;actual proposal on result builders&lt;/a&gt; highlights just how much cleverness backs them up, but also, on close reading, why they seem to be so fiddly as soon as generics and protocols come into play.&lt;/p&gt;
&lt;p&gt;The key detail – anything that looks like &lt;a href=&#34;https://en.wikipedia.org/wiki/Control_flow&#34;&gt;&amp;ldquo;control flow&amp;rdquo;&lt;/a&gt; in a Result Builder&amp;hellip; isn&amp;rsquo;t. The purported &amp;ldquo;for&amp;hellip;in&amp;rdquo; is just a closure that must have a single return. NOT a real code loop AT ALL.  No &lt;code&gt;break&lt;/code&gt;, no &lt;code&gt;continue&lt;/code&gt;&amp;hellip; nothing for-loopy about them at all.  Just a sad sad zombie for loop.  A foreach!  I&amp;rsquo;m considering taking them out of the LayerBuilder entirely like SwiftUI does because they feel so misleading in a creative coding context.&lt;/p&gt;
&lt;p&gt;In addition, the data structures the Protocol-Builder pair produces are just chock full of glue-layers that really aught to be melted out like the support material on a 3D print. Want an if statement, now you need an &lt;code&gt;_Wrapped&lt;/code&gt; struct. Want that if/else statement, now you need a &lt;code&gt;_Either&lt;/code&gt; struct. Want a for loop, now you need a &lt;code&gt;_Array&lt;/code&gt; struct. &lt;a href=&#34;https://whynotestflight.com/excuses/hello-usd-part-11-gotta-make-it-easier-to-write-file-builders/&#34;&gt;&lt;code&gt;StringNode&lt;/code&gt;&lt;/a&gt;&amp;rsquo;s resultBuilder needed none of that because it has a concrete type backing it up. Winnowing the scaffolding and returning something more ordered could be the job of a &lt;code&gt;buildFinalResult&lt;/code&gt; function perhaps, but in the mean time I&amp;rsquo;ll just load out the USD files as the &amp;ldquo;source of truth&amp;rdquo;.&lt;/p&gt;
&lt;p&gt;To have a record and for experimentation, I made a version of the code that isolates out &lt;code&gt;Layers&lt;/code&gt; and the &lt;code&gt;LayerBuilder&lt;/code&gt; with a &lt;code&gt;render&lt;/code&gt; function that prints to the console. (runs in Playground)&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;layer_playground.txt&#34;&gt;raw code file&lt;/a&gt;  | &lt;a href=&#34;https://gist.github.com/carlynorama/3e6765d4a87aaaf3fe2f69abb14764ca&#34;&gt;gist&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;At the bottom, a &lt;code&gt;IndexLoop()&lt;/code&gt; function addresses some of my concerns with the default &lt;code&gt;for&lt;/code&gt; implementation. It could be rewritten &lt;a href=&#34;https://stackoverflow.com/questions/60461796/swift-way-to-c-style-for-loop-that-alters-initial-variable&#34;&gt;with sequence&lt;/a&gt;, to take in a range, etc.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;IndexLoop&lt;/span&gt;&amp;lt;Content:Layer&amp;gt;:Layer, RenderableLayer  {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;id&lt;/span&gt;: &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt; { &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Repeating&amp;#34;&lt;/span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//var count:Int&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;elements&lt;/span&gt;: [Content]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;init&lt;/span&gt;(from start:&lt;span style=&#34;color:#91d7e3&#34;&gt;Int&lt;/span&gt; = &lt;span style=&#34;color:#f5a97f&#34;&gt;0&lt;/span&gt;, to limit:&lt;span style=&#34;color:#91d7e3&#34;&gt;Int&lt;/span&gt;, by increment:&lt;span style=&#34;color:#91d7e3&#34;&gt;Int&lt;/span&gt; = &lt;span style=&#34;color:#f5a97f&#34;&gt;1&lt;/span&gt;, @LayerBuilder content: (&lt;span style=&#34;color:#91d7e3&#34;&gt;Int&lt;/span&gt;) -&amp;gt; Content) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;.elements = []
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;for&lt;/span&gt; index &lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;stride&lt;/span&gt;(from: start, to: limit, by: increment) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;.elements.append(content(index))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;render&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;for&lt;/span&gt; element &lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt; elements {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            element._render()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;multiType2&lt;/span&gt; = Assembly {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    Square()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    IndexLoop(to: &lt;span style=&#34;color:#f5a97f&#34;&gt;3&lt;/span&gt;) { index &lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;adjusted&lt;/span&gt; = index&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;+&lt;/span&gt;&lt;span style=&#34;color:#f5a97f&#34;&gt;2&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        CircleWithParam(radius: adjusted&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;*&lt;/span&gt;&lt;span style=&#34;color:#f5a97f&#34;&gt;3&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        SquareWithParam(side: adjusted&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;*&lt;/span&gt;&lt;span style=&#34;color:#f5a97f&#34;&gt;2&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    Circle()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The resulting print out:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;Assembly&amp;lt;Tuple2Layer&amp;lt;Tuple2Layer&amp;lt;Square, IndexLoop&amp;lt;Tuple2Layer&amp;lt;CircleWithParam, SquareWithParam&amp;gt;&amp;gt;&amp;gt;, Circle&amp;gt;&amp;gt;(content: __lldb_expr_15.Tuple2Layer&amp;lt;__lldb_expr_15.Tuple2Layer&amp;lt;__lldb_expr_15.Square, __lldb_expr_15.IndexLoop&amp;lt;__lldb_expr_15.Tuple2Layer&amp;lt;__lldb_expr_15.CircleWithParam, __lldb_expr_15.SquareWithParam&amp;gt;&amp;gt;&amp;gt;, __lldb_expr_15.Circle&amp;gt;(first: __lldb_expr_15.Tuple2Layer&amp;lt;__lldb_expr_15.Square, __lldb_expr_15.IndexLoop&amp;lt;__lldb_expr_15.Tuple2Layer&amp;lt;__lldb_expr_15.CircleWithParam, __lldb_expr_15.SquareWithParam&amp;gt;&amp;gt;&amp;gt;(first: __lldb_expr_15.Square(), second: __lldb_expr_15.IndexLoop&amp;lt;__lldb_expr_15.Tuple2Layer&amp;lt;__lldb_expr_15.CircleWithParam, __lldb_expr_15.SquareWithParam&amp;gt;&amp;gt;(elements: [__lldb_expr_15.Tuple2Layer&amp;lt;__lldb_expr_15.CircleWithParam, __lldb_expr_15.SquareWithParam&amp;gt;(first: __lldb_expr_15.CircleWithParam(radius: 6), second: __lldb_expr_15.SquareWithParam(side: 4)), __lldb_expr_15.Tuple2Layer&amp;lt;__lldb_expr_15.CircleWithParam, __lldb_expr_15.SquareWithParam&amp;gt;(first: __lldb_expr_15.CircleWithParam(radius: 9), second: __lldb_expr_15.SquareWithParam(side: 6)), __lldb_expr_15.Tuple2Layer&amp;lt;__lldb_expr_15.CircleWithParam, __lldb_expr_15.SquareWithParam&amp;gt;(first: __lldb_expr_15.CircleWithParam(radius: 12), second: __lldb_expr_15.SquareWithParam(side: 8))])), second: __lldb_expr_15.Circle()))
Square
Circle with radius 6
Square with side 4
Circle with radius 9
Square with side 6
Circle with radius 12
Square with side 8
Circle
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&#34;updating-the-builders&#34;&gt;Updating the Builders&lt;/h2&gt;
&lt;p&gt;As the printout illustrates so well, the new result builder doesn&amp;rsquo;t have a pure representation of the 3D scene. Instead the &lt;code&gt;&amp;quot;Stage&amp;quot;&lt;/code&gt; &lt;code&gt;Layer&lt;/code&gt; must be traversed with functions that:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A) know how to ignore the glue-structs&lt;/li&gt;
&lt;li&gt;B) know how to return a &lt;a href=&#34;https://whynotestflight.com/excuses/hello-usd-part-11-gotta-make-it-easier-to-write-file-builders/&#34;&gt;&lt;code&gt;StringNode&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This change also improves the code&amp;rsquo;s architecture. Instead of a &lt;code&gt;USDFileBuilder&lt;/code&gt; with a &lt;code&gt;buildSphere()&lt;/code&gt; function, I now have a Sphere that conforms to a &lt;code&gt;USDRenderable&lt;/code&gt; protocol with a &lt;code&gt;forUSDA()&lt;/code&gt; function with same output.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;extension&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;Sphere&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;render&lt;/span&gt;(context: RenderContext) -&amp;gt; RenderContext {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        context &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;+&lt;/span&gt; [&lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;.forUSDA()]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;extension&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;Sphere&lt;/span&gt;:USDRenderable {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt;  &lt;span style=&#34;color:#8aadf4&#34;&gt;radiusString&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; radius:&lt;span style=&#34;color:#91d7e3&#34;&gt;Double&lt;/span&gt;) -&amp;gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;double radius = &lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;radius&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//NOTE: Multi-geometry relevant support functions live in an &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//extension of the protocol USDRenderable&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;forUSDA&lt;/span&gt;() -&amp;gt; StringNodeable {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        CurlyBraced(opening: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;def Xform &lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;&lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;.id&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;, style: .expanded) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;!&lt;/span&gt;&lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;.transformations.&lt;span style=&#34;color:#91d7e3&#34;&gt;isEmpty&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                transformStringNode(shape:&lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            CurlyBraced(opening: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;def &lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;&lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;.shapeName&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;&lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;.id.lowercased&lt;span style=&#34;color:#a6da95&#34;&gt;())&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                        style: .expanded) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;extentString&lt;span style=&#34;color:#a6da95&#34;&gt;(&lt;/span&gt;shape: &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;))&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;!&lt;/span&gt;&lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;.surfaces.&lt;span style=&#34;color:#91d7e3&#34;&gt;isEmpty&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    colorString(shape:&lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;radiusString&lt;span style=&#34;color:#a6da95&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;.radius&lt;span style=&#34;color:#a6da95&#34;&gt;))&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The &lt;code&gt;USDFileBuilder&lt;/code&gt; still exists, but it takes on a managerial role of all the supported geometries&amp;rsquo; extensions and making the initial call to the layer&amp;rsquo;s &lt;code&gt;_render()&lt;/code&gt; function.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;generateString&lt;/span&gt;(&lt;span style=&#34;color:#c6a0f6&#34;&gt;for&lt;/span&gt; stage:some Layer) -&amp;gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;items&lt;/span&gt; = stage._walk(items: [])
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;document&lt;/span&gt; = Document {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            stage._render(context: [generateHeader(defaultPrimID:items[defaultPrimIndex])])
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; document.render(style: .multilineIndented)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Note that &lt;code&gt;generateString&lt;/code&gt; had to collect the names of the prims using a &lt;code&gt;_walk&lt;/code&gt; function in order to pick one to be the default:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;extension&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;Layer&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;_walk&lt;/span&gt;(items:[&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;]) -&amp;gt; [&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;] {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;bottom&lt;/span&gt; = &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;as&lt;/span&gt;? _RenderableLayer {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; bottom.ids(items: items)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        } &lt;span style=&#34;color:#c6a0f6&#34;&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; body._walk(items: items)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;extension&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;_RenderableLayer&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;ids&lt;/span&gt;(items:[&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;]) -&amp;gt; [&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;] {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        items &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;+&lt;/span&gt; [&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;id&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The &lt;code&gt;X3DFileBuilder&lt;/code&gt; converted over nicely as well. Since I had given the &amp;ldquo;built in&amp;rdquo; &lt;code&gt;_render()&lt;/code&gt; and &lt;code&gt;render()&lt;/code&gt; to the &lt;code&gt;USDFileBuilder&lt;/code&gt;, &lt;code&gt;Layer&lt;/code&gt; and each of the scaffolding structs needed new X3D dedicated functions.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;protocol&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;_X3DRenderable&lt;/span&gt;:_RenderableLayer {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;renderX3D&lt;/span&gt;(context:RenderContext) -&amp;gt; RenderContext
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;extension&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;Layer&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;_renderX3D&lt;/span&gt;(context:RenderContext) -&amp;gt; RenderContext  {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;bottom&lt;/span&gt; = &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;as&lt;/span&gt;? _X3DRenderable {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; bottom.renderX3D(context: context)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        } &lt;span style=&#34;color:#c6a0f6&#34;&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; body._renderX3D(context: context)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;extension&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;_ArrayLayer&lt;/span&gt;:_X3DRenderable {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;renderX3D&lt;/span&gt;(context:RenderContext) -&amp;gt; RenderContext {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;         &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;myContext&lt;/span&gt; = context
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;         &lt;span style=&#34;color:#c6a0f6&#34;&gt;for&lt;/span&gt; element &lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt; elements {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;             myContext = element._renderX3D(context: myContext)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;         }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;         &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; myContext
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;     }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;extension&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;_TupleLayer&lt;/span&gt;:_X3DRenderable {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;renderX3D&lt;/span&gt;(context:RenderContext) -&amp;gt; RenderContext {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        second._renderX3D(context: &lt;span style=&#34;color:#91d7e3&#34;&gt;first&lt;/span&gt;._renderX3D(context: context))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;extension&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;_Either&lt;/span&gt;: _X3DRenderable {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;renderX3D&lt;/span&gt;(context:RenderContext) -&amp;gt; RenderContext {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;switch&lt;/span&gt; storage {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;case&lt;/span&gt; .&lt;span style=&#34;color:#91d7e3&#34;&gt;first&lt;/span&gt;(&lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;storedLayer&lt;/span&gt;):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; storedLayer._renderX3D(context: context)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;case&lt;/span&gt; .second(&lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;storedLayer&lt;/span&gt;):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; storedLayer._renderX3D(context: context)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Then Sphere needs the X3D functions as well.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;extension&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;Sphere&lt;/span&gt;:_X3DRenderable {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;renderX3D&lt;/span&gt;(context: RenderContext) -&amp;gt; RenderContext {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        context &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;+&lt;/span&gt; [&lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;.forX3D()]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;extension&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;Sphere&lt;/span&gt;:X3DRenderable {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;forX3D&lt;/span&gt;() -&amp;gt; StringNodeable {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;content&lt;/span&gt; = Tag(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Shape&amp;#34;&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            Tag(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Appearance&amp;#34;&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;!&lt;/span&gt;&lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;.surfaces.&lt;span style=&#34;color:#91d7e3&#34;&gt;isEmpty&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    materialString(&lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;.surfaces)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&amp;lt;Sphere radius=&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;&lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;.radius&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#39;&amp;gt;&amp;lt;/Sphere&amp;gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;!&lt;/span&gt;&lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;.transformations.&lt;span style=&#34;color:#91d7e3&#34;&gt;isEmpty&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;orderedTransforms&lt;/span&gt; = &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;.transformations.reversed()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;for&lt;/span&gt; item &lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt; orderedTransforms {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;attributes&lt;/span&gt; = transformAttribute(transform: item)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                content = Tag(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Transform&amp;#34;&lt;/span&gt;, attributes:attributes) { content }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; content
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Update the &lt;code&gt;generateString&lt;/code&gt; function for the &lt;code&gt;X3DFileBuilder&lt;/code&gt; went smoothly as well.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;generateString&lt;/span&gt;(&lt;span style=&#34;color:#c6a0f6&#34;&gt;for&lt;/span&gt; stage:some Layer) -&amp;gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;content&lt;/span&gt; = stage._renderX3D(context: [])
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;         &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;document&lt;/span&gt; = Document {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;             TopMatter
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;             Tag(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;X3D&amp;#34;&lt;/span&gt;, attributes: X3DAttributes) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                 head()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                 Tag(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Scene&amp;#34;&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                     content
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                 }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;             }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;         }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;         &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; document.render(style: .multilineIndented)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;With a quick&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;swift run sketchpad multiball -s
usdrecord --complexity veryhigh multiball_20230805T084605.usda multiball.png
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;et voilà:&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;multiball.png&#34; alt=&#34;Hi-Res version of the same type of clump of spheres imagery previous posts on this topic have shown.&#34;&gt;&lt;/p&gt;
&lt;p&gt;A high quality render of a multiball output like never before seen!&lt;/p&gt;
&lt;p&gt;Also still in X3D:&lt;/p&gt;
&lt;x3d width=&#39;500px&#39; height=&#39;400px&#39;&gt; 
&lt;scene&gt;
&lt;viewpoint position=&#34;0 0 20&#34;&gt;&lt;/viewpoint&gt;
&lt;inline url=&#34;multiball_20230805T084605.x3d&#34;&gt; &lt;/inline&gt; 
&lt;/scene&gt; 
&lt;/x3d&gt; 
</description>
    </item>
    
    
    
    <item>
      <title>Hello USD - Part 21: What if I refactored SketchPad to work like SwiftUI?</title>
      <link>https://whynotestflight.com/excuses/hello-usd-part-21-what-if-i-refactored-sketchpad-to-work-like-swiftui/</link>
      <pubDate>Wed, 02 Aug 2023 00:00:00 +0000</pubDate>
      
      <guid>https://whynotestflight.com/excuses/hello-usd-part-21-what-if-i-refactored-sketchpad-to-work-like-swiftui/</guid>
      <description>&lt;p&gt;I would like to be able to put items other than Spheres in my &lt;a href=&#34;https://github.com/carlynorama/SketchPad&#34;&gt;SketchPad&lt;/a&gt; generated OpenUSD files.&lt;/p&gt;
&lt;p&gt;In order to do that I need to refactor &lt;code&gt;Canvas3D&lt;/code&gt; so its existential type isn&amp;rsquo;t &lt;a href=&#34;https://github.com/carlynorama/SketchPad/blob/main/Sources/SketchPad/Canvas3D.swift&#34;&gt;&lt;code&gt;[Sphere]&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Arrays must contain items all of the same type in Swift, so a &lt;code&gt;Canvas3D&lt;/code&gt; like &lt;code&gt;[Sphere, Cube, Cone, Cube, Sphere]&lt;/code&gt; won&amp;rsquo;t just come for free.&lt;/p&gt;
&lt;p&gt;Some possible approaches -&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Option 1: Some flavor of type erasing to keep an Array as the backing data structure
&lt;ul&gt;
&lt;li&gt;an enum of allowed geometry shapes&lt;/li&gt;
&lt;li&gt;a Geometry protocol with an accompanying AnyGeometry existential/type eraser&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Option 2: Custom Collection type of some sort&lt;/li&gt;
&lt;li&gt;Option 3: A total reorg to be more like SwiftUI with a &amp;ldquo;Layer&amp;rdquo; type in the vein of SwiftUI&amp;rsquo;s View&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Since I&amp;rsquo;d already done my own data-type enum for &lt;a href=&#34;https://whynotestflight.com/excuses/hello-usd-part-11-gotta-make-it-easier-to-write-file-builders/&#34;&gt;StringNode&lt;/a&gt; I thought I&amp;rsquo;d look into Option 3. The first parts of the &lt;a href=&#34;https://talk.objc.io/collections/swiftui-layout-explained&#34;&gt;SwiftUI Layout Explained&lt;/a&gt; series and &lt;a href=&#34;https://talk.objc.io/episodes/S01E343-swiftui-style-backend-library&#34;&gt;SwiftUI-Style backend Library&lt;/a&gt; from &lt;a href=&#34;https://talk.objc.io&#34;&gt;Swift Talk&lt;/a&gt; made that possible.&lt;/p&gt;
&lt;p&gt;Complete code as gist: &lt;a href=&#34;https://gist.github.com/carlynorama/3e6765d4a87aaaf3fe2f69abb14764ca&#34;&gt;https://gist.github.com/carlynorama/3e6765d4a87aaaf3fe2f69abb14764ca&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&#34;branch-type-leaf-type&#34;&gt;Branch-Type, Leaf-Type&lt;/h2&gt;
&lt;p&gt;This method has an interesting way of knowing when a leaf is a leaf by creating two separate but interwoven protocols.&lt;/p&gt;
&lt;p&gt;First create the base protocol which looks pretty recursive and nonsensical:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;protocol&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;Layer&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    associatedtype Content:Layer
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;content&lt;/span&gt;: Content { &lt;span style=&#34;color:#c6a0f6&#34;&gt;get&lt;/span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Make a thing, whose only rule is that it has another thing that also is a thing. With zero explanation as to what makes a thing other than that. None. Shenanigans. This will be the public type everyone uses.&lt;/p&gt;
&lt;p&gt;Next make ANOTHER protocol which will be the leaf type.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//Indicate a leaf by conforming it to renderable.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;protocol&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;RenderableLayer&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;id&lt;/span&gt;:&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt; { &lt;span style=&#34;color:#c6a0f6&#34;&gt;get&lt;/span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;render&lt;/span&gt;()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;typealias&lt;/span&gt; Content = Never
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;extension&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;RenderableLayer&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;render&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;&lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;.id&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;It does NOT conform to the &lt;code&gt;Layer&lt;/code&gt; type, but items that conform to it should be able to get &lt;code&gt;Layer&lt;/code&gt; conformance for free. Therefore &lt;a href=&#34;https://www.avanderlee.com/swift/never-keyword/&#34;&gt;&lt;code&gt;Never&lt;/code&gt;&lt;/a&gt; needs to be a &lt;code&gt;Layer&lt;/code&gt;, too.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;extension&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;Layer&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;where&lt;/span&gt; Content == Never {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;content&lt;/span&gt;: Never { &lt;span style=&#34;color:#91d7e3&#34;&gt;fatalError&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;This should never be called.&amp;#34;&lt;/span&gt;) }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;extension&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;Never&lt;/span&gt;: Layer {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;id&lt;/span&gt;:&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt; { &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Never&amp;#34;&lt;/span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;typealias&lt;/span&gt; Content = Never
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;walking-the-tree&#34;&gt;Walking the Tree&lt;/h2&gt;
&lt;p&gt;When walking the tree, how will we know if we&amp;rsquo;re at a leaf or not? The &lt;code&gt;_render&lt;/code&gt; function on &lt;code&gt;Layer&lt;/code&gt; will check if the current node conforms to the leaf protocol, and if so, get the leaf&amp;rsquo;s render function, which exits the loop. Otherwise, the current layer will dive down into its content&amp;rsquo;s .&lt;code&gt;_render&lt;/code&gt;, which must exist, because it must have content that also conforms to &lt;code&gt;Layer&lt;/code&gt;. If implementing this for real the current location in the tree or other context information could be passed through via parameters in the render functions, i.e. &lt;code&gt;render(context:SomeContextType)&lt;/code&gt;&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;extension&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;Layer&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;_render&lt;/span&gt;()  {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;leaf&lt;/span&gt; = &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;as&lt;/span&gt;? RenderableLayer {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            leaf.render()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        } &lt;span style=&#34;color:#c6a0f6&#34;&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            content._render()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;building-a-layer&#34;&gt;Building a Layer&lt;/h2&gt;
&lt;p&gt;Let&amp;rsquo;s say my goal is something like:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;insert&lt;/span&gt; = Assembly {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    Triangle()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    Triangle()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    Triangle()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;test&lt;/span&gt; = Assembly {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    Circle()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    Square()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#91d7e3&#34;&gt;insert&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    Circle()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    Circle()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;test._render()
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;to resulting in a printed list like:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Circle
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Square
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Triangle
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Triangle
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Triangle
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Circle
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Circle
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;SwiftUI itself uses the new &lt;a href=&#34;https://forums.swift.org/t/improved-result-builder-implementation-in-swift-5-8/63192&#34;&gt;easier resultBuilder&lt;/a&gt; to do something like:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;@resultBuilder
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;enum&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;LayerBuilder&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;buildPartialBlock&lt;/span&gt;&amp;lt;L: Layer&amp;gt;(&lt;span style=&#34;color:#91d7e3&#34;&gt;first&lt;/span&gt;: L) -&amp;gt; some Layer {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#91d7e3&#34;&gt;first&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;buildPartialBlock&lt;/span&gt;&amp;lt;L0: Layer, L1: Layer&amp;gt;(accumulated: L0, next: L1) -&amp;gt; some Layer {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        Tuple2Layer(&lt;span style=&#34;color:#91d7e3&#34;&gt;first&lt;/span&gt;: accumulated, second: next)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;Tuple2Layer&lt;/span&gt;&amp;lt;First:Layer, Second:Layer&amp;gt;: Layer, RenderableLayer {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;id&lt;/span&gt;:&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt; { &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Tuple&amp;#34;&lt;/span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;first&lt;/span&gt;: First
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;second&lt;/span&gt;: Second
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;init&lt;/span&gt;(&lt;span style=&#34;color:#91d7e3&#34;&gt;first&lt;/span&gt;:First, second:Second) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;.&lt;span style=&#34;color:#91d7e3&#34;&gt;first&lt;/span&gt; = &lt;span style=&#34;color:#91d7e3&#34;&gt;first&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;.second = second
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;render&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#91d7e3&#34;&gt;first&lt;/span&gt;._render()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        second._render()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;A &lt;a href=&#34;https://developer.apple.com/documentation/swiftui/tupleview&#34;&gt;TupleView&lt;/a&gt; really exists in SwiftUI. It&amp;rsquo;s an aggregating type for exactly this situation.&lt;/p&gt;
&lt;p&gt;An Assembly can use the &lt;code&gt;LayerBuilder&lt;/code&gt; for an initializer:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;Assembly&lt;/span&gt;&amp;lt;Content:Layer&amp;gt;:Layer {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;content&lt;/span&gt;: Content
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;init&lt;/span&gt;(@LayerBuilder content: () -&amp;gt; Content) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;.content = content()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And the geometries can all conform to Layer &amp;amp; RenderableLayer:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;protocol&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;Geometry&lt;/span&gt;: Layer &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;amp;&lt;/span&gt; RenderableLayer {}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;Circle&lt;/span&gt;:Geometry {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;id&lt;/span&gt;:&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt; { &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Circle&amp;#34;&lt;/span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;Square&lt;/span&gt;:Geometry {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;id&lt;/span&gt;:&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt; { &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Square&amp;#34;&lt;/span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;Triangle&lt;/span&gt;:Geometry {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;id&lt;/span&gt;:&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt; { &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Triangle&amp;#34;&lt;/span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And the goal code prints out the goal result.&lt;/p&gt;
&lt;p&gt;If we print the test Assembly, we can see that the resulting memory bristles with &lt;code&gt;Tuple2Layers&lt;/code&gt;.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(test)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//results in &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Assembly&amp;lt;Tuple2Layer&amp;lt;Tuple2Layer&amp;lt;Tuple2Layer&amp;lt;Tuple2Layer&amp;lt;Circle, Square&amp;gt;, 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Assembly&amp;lt;Tuple2Layer&amp;lt;Tuple2Layer&amp;lt;Triangle, Triangle&amp;gt;, Triangle&amp;gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;gt;&amp;gt;&lt;/span&gt;, Circle&amp;gt;, 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Circle&amp;gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;gt;&lt;/span&gt;(content: __lldb_expr_55.Tuple2Layer&amp;lt;__lldb_expr_55.
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Tuple2Layer&amp;lt;__lldb_expr_55.Tuple2Layer&amp;lt;__lldb_expr_55.
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Tuple2Layer&amp;lt;__lldb_expr_55.Circle, __lldb_expr_55.Square&amp;gt;, __lldb_expr_55.
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Assembly&amp;lt;__lldb_expr_55.Tuple2Layer&amp;lt;__lldb_expr_55.
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Tuple2Layer&amp;lt;__lldb_expr_55.Triangle, __lldb_expr_55.Triangle&amp;gt;, 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;__lldb_expr_55.Triangle&amp;gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;gt;&amp;gt;&lt;/span&gt;, __lldb_expr_55.Circle&amp;gt;, __lldb_expr_55.Circle&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;color:#91d7e3&#34;&gt;first&lt;/span&gt;: __lldb_expr_55.Tuple2Layer&amp;lt;__lldb_expr_55.Tuple2Layer&amp;lt;__lldb_expr_55.
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Tuple2Layer&amp;lt;__lldb_expr_55.Circle, __lldb_expr_55.Square&amp;gt;, __lldb_expr_55.
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Assembly&amp;lt;__lldb_expr_55.Tuple2Layer&amp;lt;__lldb_expr_55.
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Tuple2Layer&amp;lt;__lldb_expr_55.Triangle, __lldb_expr_55.Triangle&amp;gt;, 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;__lldb_expr_55.Triangle&amp;gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;gt;&amp;gt;&lt;/span&gt;, __lldb_expr_55.Circle&amp;gt;(&lt;span style=&#34;color:#91d7e3&#34;&gt;first&lt;/span&gt;: __lldb_expr_55.
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Tuple2Layer&amp;lt;__lldb_expr_55.Tuple2Layer&amp;lt;__lldb_expr_55.Circle, __lldb_expr_55.
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Square&amp;gt;, __lldb_expr_55.Assembly&amp;lt;__lldb_expr_55.Tuple2Layer&amp;lt;__lldb_expr_55.
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Tuple2Layer&amp;lt;__lldb_expr_55.Triangle, __lldb_expr_55.Triangle&amp;gt;, 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;__lldb_expr_55.Triangle&amp;gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;gt;&amp;gt;&lt;/span&gt;(&lt;span style=&#34;color:#91d7e3&#34;&gt;first&lt;/span&gt;: __lldb_expr_55.Tuple2Layer&amp;lt;__lldb_expr_55.
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Circle, __lldb_expr_55.Square&amp;gt;(&lt;span style=&#34;color:#91d7e3&#34;&gt;first&lt;/span&gt;: __lldb_expr_55.Circle(), second: 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;__lldb_expr_55.Square()), second: __lldb_expr_55.Assembly&amp;lt;__lldb_expr_55.
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Tuple2Layer&amp;lt;__lldb_expr_55.Tuple2Layer&amp;lt;__lldb_expr_55.Triangle, 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;__lldb_expr_55.Triangle&amp;gt;, __lldb_expr_55.Triangle&amp;gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;gt;&lt;/span&gt;(content: __lldb_expr_55.
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Tuple2Layer&amp;lt;__lldb_expr_55.Tuple2Layer&amp;lt;__lldb_expr_55.Triangle, 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;__lldb_expr_55.Triangle&amp;gt;, __lldb_expr_55.Triangle&amp;gt;(&lt;span style=&#34;color:#91d7e3&#34;&gt;first&lt;/span&gt;: __lldb_expr_55.
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Tuple2Layer&amp;lt;__lldb_expr_55.Triangle, __lldb_expr_55.Triangle&amp;gt;(&lt;span style=&#34;color:#91d7e3&#34;&gt;first&lt;/span&gt;: 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;__lldb_expr_55.Triangle(), second: __lldb_expr_55.Triangle()), second: 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;__lldb_expr_55.Triangle()))), second: __lldb_expr_55.Circle()), second: 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;__lldb_expr_55.Circle()))
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;I&amp;rsquo;m not convinced, aesthetically, I like this as the resting storage for my Stage.  It does not &amp;hellip;&lt;em&gt;feel&lt;/em&gt;&amp;hellip; composed.  It feels smashed.&lt;/p&gt;
&lt;h2 id=&#34;next-steps&#34;&gt;Next Steps&lt;/h2&gt;
&lt;p&gt;Right now I have &lt;code&gt;FileBuilders&lt;/code&gt; (&lt;code&gt;USD&lt;/code&gt; or &lt;code&gt;X3D&lt;/code&gt;) that can take in a &amp;ldquo;Stage&amp;rdquo;, munch through the data to spit out the needed text files. This model feels more like I&amp;rsquo;d have to create a Builder-Context Class to give to the render function which will pass it (by reference?) through the tree collecting each nodes contribution?&lt;/p&gt;
&lt;p&gt;Also, the advantage of this Option 3 approach over a hard coded list of allowed geometries in an enum is that more kinds can be added than I can think of via extensions. But how to handle the render information not being available for also-addable Builder type?&lt;/p&gt;
&lt;p&gt;So plenty more staring off into space and pushing pieces of code around until it feels right to do.&lt;/p&gt;
&lt;h2 id=&#34;references&#34;&gt;References&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;NotSwiftUI series: &lt;a href=&#34;https://talk.objc.io/episodes/S01E225-view-protocols-and-shapes&#34;&gt;https://talk.objc.io/episodes/S01E225-view-protocols-and-shapes&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Using SwiftUI to make a server path builder: &lt;a href=&#34;https://talk.objc.io/episodes/S01E343-swiftui-style-backend-library&#34;&gt;https://talk.objc.io/episodes/S01E343-swiftui-style-backend-library&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;More on TupleView: &lt;a href=&#34;https://forums.swift.org/t/swiftui-viewbuilder-result-is-a-tupleview-how-is-apple-using-it-and-able-to-avoid-turning-things-into-anyview/28181&#34;&gt;https://forums.swift.org/t/swiftui-viewbuilder-result-is-a-tupleview-how-is-apple-using-it-and-able-to-avoid-turning-things-into-anyview/28181&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Example of the Tuple/ResultBuilder pattern: &lt;a href=&#34;https://github.com/apple/swift-certificates/blob/8debe3f20df931a29d0e5834fd8101fb49feea42/Sources/X509/Verifier/AnyPolicy.swift#L41&#34;&gt;https://github.com/apple/swift-certificates/blob/8debe3f20df931a29d0e5834fd8101fb49feea42/Sources/X509/Verifier/AnyPolicy.swift#L41&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</description>
    </item>
    
    
    
    <item>
      <title>Hello USD - Part 20: Hello usdrecord</title>
      <link>https://whynotestflight.com/excuses/hello-usd-part-20-hello-usdrecord/</link>
      <pubDate>Sat, 29 Jul 2023 00:00:00 +0000</pubDate>
      
      <guid>https://whynotestflight.com/excuses/hello-usd-part-20-hello-usdrecord/</guid>
      <description>&lt;p&gt;I&amp;rsquo;ve mostly been looking at my usda files as screen grabs from &lt;code&gt;QuickLook&lt;/code&gt;. It came up on the &lt;a href=&#34;https://wiki.aswf.io/display/WGUSD/USD+Working+Group&#34;&gt;ASFWG&lt;/a&gt; slack that the utility &lt;a href=&#34;https://openusd.org/release/toolset.html#usdrecord&#34;&gt;&lt;code&gt;usdrecord&lt;/code&gt;&lt;/a&gt;, included in the default build, will make png files. Several other types, too!&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;usage: usdrecord [-h] [--mask PRIMPATH[,PRIMPATH...]] [--camera CAMERA]
                 [--defaultTime | --frames FRAMESPEC[,FRAMESPEC...]]
                 [--complexity {low,medium,high,veryhigh}]
                 [--colorCorrectionMode {disabled,sRGB,openColorIO}]
                 [--renderer {GL,Embree,Prman}]
                 [--imageWidth IMAGEWIDTH]
                 usdFilePath outputImagePath
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&#34;what-it-looks-like&#34;&gt;What it looks like&lt;/h2&gt;
&lt;p&gt;The &lt;code&gt;veryhigh&lt;/code&gt; complexity setting for &lt;code&gt;usdrecord&lt;/code&gt; makes positively luscious output. The default output width is &lt;a href=&#34;https://github.com/PixarAnimationStudios/OpenUSD/blob/release/pxr/usdImaging/bin/usdrecord/usdrecord.py#L145&#34;&gt;960&lt;/a&gt; pixels. The documentation says it will then pick the width based on the camera&amp;rsquo;s aspect ratio. I don&amp;rsquo;t have a camera in my scene so I was curious to find out that the height would be. Turns out it was 700 pixels, TIL the &lt;a href=&#34;https://en.wikipedia.org/wiki/Academy_ratio&#34;&gt;Academy Ratio&lt;/a&gt; is a thing! Also, because I don&amp;rsquo;t have any animation stored in this USD file, I did not need to add the ###&amp;rsquo;s to the name for the frame numbers. Like with &lt;code&gt;usdcat&lt;/code&gt;, the output filename chooses the file type.&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;usdrecord --complexity veryhigh input.usda output.png
&lt;/code&gt;&lt;/pre&gt;&lt;table&gt;
  &lt;thead&gt;
      &lt;tr&gt;
          &lt;th&gt;usdrecord&lt;/th&gt;
          &lt;th&gt;QuickLook&lt;/th&gt;
      &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;img src=&#34;finalring_XXX.png&#34; alt=&#34;&#34;&gt;&lt;/td&gt;
          &lt;td&gt;&lt;img src=&#34;final_ring.png&#34; alt=&#34;&#34;&gt;&lt;/td&gt;
      &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;I then made a set of bigger images (5700 pixels across), one at each complexity, and sliced them up with imagemagick to compare them.&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;usdrecord --complexity veryhigh --imageWidth 5700 input.usda output.png
convert finalring_forT_vh_5700.png -crop 250x250  +repage  +adjoin veryhigh/finalring_vh_%02d.png
convert finalring_vh_133.png -crop &amp;#34;+170+170&amp;#34; -resize 240x240 closeup_vh.png
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The table below shows one of the 250x250 sections cut out of each of the complexity examples in the top row. In the second row a close up of the edge of the corresponding sphere in the top row.&lt;/p&gt;
&lt;table&gt;
  &lt;thead&gt;
      &lt;tr&gt;
          &lt;th&gt;Low&lt;/th&gt;
          &lt;th&gt;Med&lt;/th&gt;
          &lt;th&gt;High&lt;/th&gt;
          &lt;th&gt;Very High&lt;/th&gt;
      &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;img src=&#34;finalring_low_133.png&#34; alt=&#34;&#34;&gt;&lt;/td&gt;
          &lt;td&gt;&lt;img src=&#34;finalring_medium_133.png&#34; alt=&#34;&#34;&gt;&lt;/td&gt;
          &lt;td&gt;&lt;img src=&#34;finalring_high_133.png&#34; alt=&#34;&#34;&gt;&lt;/td&gt;
          &lt;td&gt;&lt;img src=&#34;finalring_vh_133.png&#34; alt=&#34;&#34;&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;img src=&#34;closeup_low.png&#34; alt=&#34;&#34;&gt;&lt;/td&gt;
          &lt;td&gt;&lt;img src=&#34;closeup_medium.png&#34; alt=&#34;&#34;&gt;&lt;/td&gt;
          &lt;td&gt;&lt;img src=&#34;closeup_high.png&#34; alt=&#34;&#34;&gt;&lt;/td&gt;
          &lt;td&gt;&lt;img src=&#34;closeup_vh.png&#34; alt=&#34;&#34;&gt;&lt;/td&gt;
      &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;The png files &lt;code&gt;usdrecord&lt;/code&gt; makes are a bit chonky. They&amp;rsquo;re well served by a slim down.  I used &lt;a href=&#34;https://imageoptim.com/mac&#34;&gt;ImageOptim&lt;/a&gt;, for convenience. What is nice? That chonkness comes completely from the pixel data&amp;rsquo;s lack of compression. &lt;code&gt;usdrecord&lt;/code&gt; does not load the files up with meta data or anything like that.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;ImageOptim_slimdown.png&#34; alt=&#34;&#34;&gt;&lt;/p&gt;
&lt;h2 id=&#34;usdrecord-under-the-hood&#34;&gt;usdrecord Under The Hood&lt;/h2&gt;
&lt;p&gt;I haven&amp;rsquo;t touched the rendering aspects of OpenUSD at all, and have very little understanding of what Hydra is and how it works. PNG files, on the other hand, I feel like &lt;a href=&#34;https://whynotestflight.com/excuses/pngs-are-cool/&#34;&gt;I have a small handle&lt;/a&gt; on those. So I went looking for what was under the hood because that may have been my way into the Renderer/RenderDelegate aspect of OpenUSD. I may use the term renderer imprecisely in the following section, per what it means in OpenUSD specifically. I&amp;rsquo;m still trying to get what role a capital &amp;ldquo;R&amp;rdquo; renderer does and what it doesn&amp;rsquo;t.&lt;/p&gt;
&lt;p&gt;The trail starts with &lt;a href=&#34;https://github.com/PixarAnimationStudios/OpenUSD/blob/10b62439e9242a55101cf8b200f2c7e02420e1b0/pxr/usdImaging/bin/usdrecord/usdrecord.py#L4&#34;&gt;&lt;code&gt;usdrecord&lt;/code&gt;&lt;/a&gt; a shebanged python script that lives in the bin folder. I can&amp;rsquo;t otool check the dependencies, because it&amp;rsquo;s not actually a binary.&lt;/p&gt;
&lt;p&gt;I did take special note of line 190: &lt;code&gt;frameRecorder = UsdAppUtils.FrameRecorder(rendererPluginId, args.gpuEnabled)&lt;/code&gt;. This frameRecorder receives all the CLI&amp;rsquo;s arguments, and actually appears to do the writing to disk with &lt;code&gt;frameRecorder.Record&lt;/code&gt; on line 203.&lt;/p&gt;
&lt;p&gt;I found its definition at &lt;a href=&#34;https://github.com/PixarAnimationStudios/OpenUSD/blob/10b62439e9242a55101cf8b200f2c7e02420e1b0/pxr/usdImaging/usdAppUtils/frameRecorder.cpp#L49&#34;&gt;https://github.com/PixarAnimationStudios/OpenUSD/blob/10b62439e9242a55101cf8b200f2c7e02420e1b0/pxr/usdImaging/usdAppUtils/frameRecorder.cpp#L49&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Note that this is a C++ file, so the compiled C++ has to live somewhere. This looked promising:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;cd $BUILD_DESTINATION/build/USD/pxr/usd/usdUtils/
otool -L ./libusd_usdUtils.dylib
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Got me this information:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;./libusd_usdUtils.dylib:
	@rpath/libusd_usdUtils.dylib (compatibility version 0.0.0, current version 0.0.0)
	@rpath/libusd_usdShade.dylib (compatibility version 0.0.0, current version 0.0.0)
	@rpath/libboost_python39.dylib (compatibility version 0.0.0, current version 0.0.0)
	@rpath/libusd_usdGeom.dylib (compatibility version 0.0.0, current version 0.0.0)
	@rpath/libusd_usd.dylib (compatibility version 0.0.0, current version 0.0.0)
	@rpath/libusd_kind.dylib (compatibility version 0.0.0, current version 0.0.0)
	@rpath/libusd_pcp.dylib (compatibility version 0.0.0, current version 0.0.0)
	@rpath/libusd_sdr.dylib (compatibility version 0.0.0, current version 0.0.0)
	@rpath/libusd_ndr.dylib (compatibility version 0.0.0, current version 0.0.0)
	@rpath/libusd_sdf.dylib (compatibility version 0.0.0, current version 0.0.0)
	@rpath/libusd_ar.dylib (compatibility version 0.0.0, current version 0.0.0)
	@rpath/libusd_vt.dylib (compatibility version 0.0.0, current version 0.0.0)
	@rpath/libusd_gf.dylib (compatibility version 0.0.0, current version 0.0.0)
	@rpath/libusd_plug.dylib (compatibility version 0.0.0, current version 0.0.0)
	@rpath/libusd_work.dylib (compatibility version 0.0.0, current version 0.0.0)
	@rpath/libusd_trace.dylib (compatibility version 0.0.0, current version 0.0.0)
	@rpath/libusd_js.dylib (compatibility version 0.0.0, current version 0.0.0)
	@rpath/libusd_tf.dylib (compatibility version 0.0.0, current version 0.0.0)
	@rpath/libusd_arch.dylib (compatibility version 0.0.0, current version 0.0.0)
	/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1319.100.3)
	/Users/labtanza/.pyenv/versions/3.9.17/lib/libpython3.9.dylib (compatibility version 3.9.0, current version 3.9.0)
	@rpath/libtbb.dylib (compatibility version 0.0.0, current version 0.0.0)
	/usr/lib/libc++.1.dylib (compatibility version 1.0.0, current version 1500.65.0)
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Hunh. No &lt;code&gt;libpng&lt;/code&gt;, which I was expecting to see.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;frameRecorder.cpp&lt;/code&gt; does have functions that use the parameters passed into usdrecord along with a the timestamp to move the camera and resolve to scene graph to provide the renderer with the information it needs to actually do the rendering. That renderer appears to be an parameter in the initializer: &lt;code&gt;_imagingEngine(HdDriver(), rendererPluginId, gpuEnabled)&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Also in framerRecorder.cpp is the definition for a &lt;code&gt;TextureBufferWriter&lt;/code&gt;. Its initializer takes in the &lt;code&gt;FrameRecorder&lt;/code&gt;&amp;rsquo;s &lt;code&gt;_imagingEngine&lt;/code&gt;, so on line 154 we can see its of type &lt;code&gt;UsdImagingGLEngine&lt;/code&gt;.  Additionally we can learn that the &lt;code&gt;TextureBufferWriter&lt;/code&gt; write function uses &lt;code&gt;HioImage::OpenForWriting&lt;/code&gt;.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/PixarAnimationStudios/OpenUSD/blob/10b62439e9242a55101cf8b200f2c7e02420e1b0/pxr/usdImaging/usdImagingGL/engine.h#L95&#34;&gt;https://github.com/PixarAnimationStudios/OpenUSD/blob/10b62439e9242a55101cf8b200f2c7e02420e1b0/pxr/usdImaging/usdImagingGL/engine.h#L95&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/PixarAnimationStudios/OpenUSD/blob/10b62439e9242a55101cf8b200f2c7e02420e1b0/pxr/imaging/hio/image.cpp#L65&#34;&gt;https://github.com/PixarAnimationStudios/OpenUSD/blob/10b62439e9242a55101cf8b200f2c7e02420e1b0/pxr/imaging/hio/image.cpp#L65&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/PixarAnimationStudios/OpenUSD/blob/10b62439e9242a55101cf8b200f2c7e02420e1b0/pxr/imaging/hio/image.h#L139&#34;&gt;https://github.com/PixarAnimationStudios/OpenUSD/blob/10b62439e9242a55101cf8b200f2c7e02420e1b0/pxr/imaging/hio/image.h#L139&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/PixarAnimationStudios/OpenUSD/blob/10b62439e9242a55101cf8b200f2c7e02420e1b0/pxr/imaging/hio/stbImage.cpp#L75&#34;&gt;https://github.com/PixarAnimationStudios/OpenUSD/blob/10b62439e9242a55101cf8b200f2c7e02420e1b0/pxr/imaging/hio/stbImage.cpp#L75&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;HIOImage appears to have a subclass, &lt;code&gt;Hio_StbImage&lt;/code&gt; that uses the stb library to do its reading and writing.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/PixarAnimationStudios/OpenUSD/tree/10b62439e9242a55101cf8b200f2c7e02420e1b0/pxr/imaging/hio/stb&#34;&gt;https://github.com/PixarAnimationStudios/OpenUSD/tree/10b62439e9242a55101cf8b200f2c7e02420e1b0/pxr/imaging/hio/stb&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/nothings/stb&#34;&gt;https://github.com/nothings/stb&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/PixarAnimationStudios/OpenUSD/blob/10b62439e9242a55101cf8b200f2c7e02420e1b0/pxr/imaging/hio/stb/stb_image_write.h#L176&#34;&gt;https://github.com/PixarAnimationStudios/OpenUSD/blob/10b62439e9242a55101cf8b200f2c7e02420e1b0/pxr/imaging/hio/stb/stb_image_write.h#L176&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;AND &lt;code&gt;stb&lt;/code&gt; does not appear to use our friend &lt;a href=&#34;https://github.com/carlynorama/SwiftLIBPNG&#34;&gt;&lt;code&gt;libpng&lt;/code&gt;&lt;/a&gt;, it compresses the data itself.&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;   The PNG output is not optimal; it is 20-50% larger than the file
   written by a decent optimizing implementation; though providing a custom
   zlib compress function (see STBIW_ZLIB_COMPRESS) can mitigate that.
   This library is designed for source code compactness and simplicity,
   not optimal image file size or run-time performance.
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Totally reasonable trade off as the stb library means usdrecord could potentially save &lt;a href=&#34;https://github.com/PixarAnimationStudios/OpenUSD/blob/10b62439e9242a55101cf8b200f2c7e02420e1b0/pxr/imaging/hio/stb/stb_image.h&#34;&gt;JPEG, PNG, TGA, BMP, PSD, GIF, HDR, PIC and PNM&lt;/a&gt; with very very little extra code. What &lt;code&gt;usdrecord&lt;/code&gt; will output: &lt;a href=&#34;https://github.com/PixarAnimationStudios/OpenUSD/blob/10b62439e9242a55101cf8b200f2c7e02420e1b0/pxr/imaging/hio/plugInfo.json#L5&#34;&gt;[&amp;ldquo;bmp&amp;rdquo;, &amp;ldquo;jpg&amp;rdquo;, &amp;ldquo;jpeg&amp;rdquo;, &amp;ldquo;png&amp;rdquo;, &amp;ldquo;tga&amp;rdquo;, &amp;ldquo;hdr&amp;rdquo;]&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;I had been looking for something that depended on libpng because the &lt;code&gt;build_usd.py&lt;/code&gt; script manages a &lt;a href=&#34;https://github.com/PixarAnimationStudios/OpenUSD/blob/10b62439e9242a55101cf8b200f2c7e02420e1b0/build_scripts/build_usd.py#L1125&#34;&gt;libpng install&lt;/a&gt;, although&amp;hellip; none of the code in the Pixar/OpenUSD repo directly includes a &lt;code&gt;png.h&lt;/code&gt;. The optional install of &lt;a href=&#34;https://github.com/OpenImageIO/&#34;&gt;OpenImageIO&lt;/a&gt;, which gets used for the &amp;ldquo;loading and saving of texture files&amp;rdquo; does use it. (&lt;a href=&#34;https://github.com/PixarAnimationStudios/OpenUSD/blob/10b62439e9242a55101cf8b200f2c7e02420e1b0/build_scripts/build_usd.py#L2300C1-L2301C79&#34;&gt;build_usd.py line 2300&lt;/a&gt;) I am unsure at the moment which parts of OpenUSD will call OpenImageIO, if installed.&lt;/p&gt;
&lt;p&gt;Like with &lt;a href=&#34;https://github.com/PixarAnimationStudios/OpenUSD/blob/10b62439e9242a55101cf8b200f2c7e02420e1b0/pxr/imaging/hio/stbImage.cpp#L75&#34;&gt;stb&lt;/a&gt; there also seems to be a subclass of HIOImage that uses &lt;a href=&#34;https://github.com/PixarAnimationStudios/OpenUSD/blob/10b62439e9242a55101cf8b200f2c7e02420e1b0/pxr/imaging/plugin/hioOiio/oiioImage.cpp#L67&#34;&gt;OpenImageIO&lt;/a&gt;? But only for the &lt;a href=&#34;https://github.com/PixarAnimationStudios/OpenUSD/blob/10b62439e9242a55101cf8b200f2c7e02420e1b0/pxr/imaging/plugin/hioOiio/plugInfo.json#L8&#34;&gt;image types not handled by stb&lt;/a&gt;? These types are NOT made available to &lt;code&gt;usdrecord&lt;/code&gt; from what I can tell trying to use them on a default build.&lt;/p&gt;
&lt;h2 id=&#34;fin&#34;&gt;Fin&lt;/h2&gt;
&lt;p&gt;I don&amp;rsquo;t have a totally firm grasp on how OpenUSD picks which subclass to use for its &lt;code&gt;HioImage::OpenForWriting&lt;/code&gt;. I&amp;rsquo;m intrigued that there seems to be a plugin architecture. I do feel good about tracking the journey of a little ol&amp;rsquo; usda all the way from ascii to png.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;FrameRecorder&lt;/code&gt; (a Renderer?, a RenderDelegate? None of the above?) loads the usd file, moves the camera, gets the scene info ready, stuffs it into&amp;hellip;&lt;/li&gt;
&lt;li&gt;a &lt;code&gt;UsdImagingGLEngine&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Which then gets handed of to a &lt;code&gt;TextureBufferWriter&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Which leans on a &lt;code&gt;HioImage&lt;/code&gt;/&lt;code&gt;stb&lt;/code&gt; to get the pixels out into &lt;code&gt;stdio&lt;/code&gt; for writing.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Issue to keep an eye on: &lt;a href=&#34;https://github.com/PixarAnimationStudios/OpenUSD/issues/2556&#34;&gt;https://github.com/PixarAnimationStudios/OpenUSD/issues/2556&lt;/a&gt;&lt;/p&gt;
</description>
    </item>
    
    
    
    <item>
      <title>Hello USD - Part 19: I just plain skipped over latitude and longitude</title>
      <link>https://whynotestflight.com/excuses/hello-usd-part-19-i-just-plain-skipped-over-latitude-and-longitude/</link>
      <pubDate>Thu, 27 Jul 2023 00:00:00 +0000</pubDate>
      
      <guid>https://whynotestflight.com/excuses/hello-usd-part-19-i-just-plain-skipped-over-latitude-and-longitude/</guid>
      <description>&lt;script type=&#39;text/javascript&#39; src=&#39;https://www.x3dom.org/download/x3dom.js&#39;&gt; &lt;/script&gt; 
&lt;p&gt;Taking an easy day today while I ponder how to refactor Canvas3D to be composable like OpenUSD.&lt;/p&gt;
&lt;p&gt;It&amp;rsquo;s pretty hilarious I went straight for a &lt;a href=&#34;https://whynotestflight.com/excuses/hello-usd-part-18-i-can-make-a-sphere-out-of-spheres/&#34;&gt;fibonacci spiral&lt;/a&gt; instead of lat/long style Spheres placement. I wanted even and the fibonacci style makes distribution even.  Latitude and longitude style coordinates cannot be even as they try to lay a cartesian grid on a surface that&amp;rsquo;s not flat.&lt;/p&gt;
&lt;p&gt;I made two styles of spheres. One style &lt;code&gt;findCoordinate_dy&lt;/code&gt; treats the parallels as slices, moving the same 𝚫y down the spindle each time. The other style, &lt;code&gt;findCoordinate_dtheta&lt;/code&gt;, creates the classic latitude rings; the polar angle gets incremented.&lt;/p&gt;
&lt;p&gt;One gets gappy at the poles, the other gets gappy at the equator.&lt;/p&gt;
&lt;p&gt;How they looked when I was done:&lt;/p&gt;
&lt;table&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;x3d width=&#39;300px&#39; height=&#39;300px&#39;&gt;&lt;scene&gt;
&lt;viewpoint position=&#34;0 0 50&#34;&gt;&lt;/viewpoint&gt;
&lt;inline url=&#34;dy_20230726T153646.x3d&#34;&gt; &lt;/inline&gt; 
&lt;/scene&gt; 
&lt;/x3d&gt; 
&lt;/td&gt;
&lt;td&gt;
&lt;x3d width=&#39;300px&#39; height=&#39;300px&#39;&gt; 
&lt;scene&gt;
&lt;viewpoint position=&#34;0 0 50&#34;&gt;&lt;/viewpoint&gt;
&lt;inline url=&#34;dtheta_20230726T153325.x3d&#34;&gt; &lt;/inline&gt; 
&lt;/scene&gt; 
&lt;/x3d&gt; 
&lt;/td&gt;
&lt;/table&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;dy_20230726T153646.usda&#34;&gt;delta y usda file&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;dtheta_20230726T153325.usda&#34;&gt;delta theta usda file&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;first-pass&#34;&gt;First Pass&lt;/h2&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//  LatLongSatellites.swift&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//  &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//  Created by Carlyn Maw on 7/26/23.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;Foundation&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//http://www.songho.ca/opengl/gl_sphere.html&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;LatLongSatellites&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;init&lt;/span&gt;(meridianCount:&lt;span style=&#34;color:#91d7e3&#34;&gt;Int&lt;/span&gt;, 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                parallelCount:&lt;span style=&#34;color:#91d7e3&#34;&gt;Int&lt;/span&gt;, 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                radius:&lt;span style=&#34;color:#91d7e3&#34;&gt;Double&lt;/span&gt;, 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                ratio:&lt;span style=&#34;color:#91d7e3&#34;&gt;Double&lt;/span&gt; = &lt;span style=&#34;color:#f5a97f&#34;&gt;0.1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    ) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;.meridianCount = meridianCount
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;.parallelCount = parallelCount
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;.radius = radius
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;.ratio = ratio
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;meridianCount&lt;/span&gt;:&lt;span style=&#34;color:#91d7e3&#34;&gt;Int&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;parallelCount&lt;/span&gt;:&lt;span style=&#34;color:#91d7e3&#34;&gt;Int&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;radius&lt;/span&gt;:&lt;span style=&#34;color:#91d7e3&#34;&gt;Double&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;ratio&lt;/span&gt;:&lt;span style=&#34;color:#91d7e3&#34;&gt;Double&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;tau&lt;/span&gt; = &lt;span style=&#34;color:#91d7e3&#34;&gt;Double&lt;/span&gt;.pi &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;*&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;2&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;buildStage&lt;/span&gt;() -&amp;gt; Canvas3D {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;sun_color&lt;/span&gt; = &lt;span style=&#34;color:#f5a97f&#34;&gt;0.9&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;sphere_radius&lt;/span&gt; = radius&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;*&lt;/span&gt;ratio
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;base_lat_dy&lt;/span&gt; = &lt;span style=&#34;color:#f5a97f&#34;&gt;2.0&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;/&lt;/span&gt;&lt;span style=&#34;color:#91d7e3&#34;&gt;Double&lt;/span&gt;(parallelCount&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;-&lt;/span&gt;&lt;span style=&#34;color:#f5a97f&#34;&gt;1&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;base_polar_deflection&lt;/span&gt; = &lt;span style=&#34;color:#91d7e3&#34;&gt;Double&lt;/span&gt;.pi&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;/&lt;/span&gt;&lt;span style=&#34;color:#91d7e3&#34;&gt;Double&lt;/span&gt;(parallelCount&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;-&lt;/span&gt;&lt;span style=&#34;color:#f5a97f&#34;&gt;1&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;base_long_dphi&lt;/span&gt; =  tau&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;/&lt;/span&gt;&lt;span style=&#34;color:#91d7e3&#34;&gt;Double&lt;/span&gt;(meridianCount)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; Canvas3D {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            Sphere(radius: sphere_radius)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                .color(red: sun_color, green: sun_color, blue: sun_color)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;for&lt;/span&gt; i &lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;0.&lt;/span&gt;.&amp;lt;parallelCount {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#c6a0f6&#34;&gt;for&lt;/span&gt; j &lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;0.&lt;/span&gt;.&amp;lt;meridianCount {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    Sphere(radius: sphere_radius)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                        .color(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                            red: &lt;span style=&#34;color:#f5a97f&#34;&gt;0.3&lt;/span&gt;, &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//(Double(j)/Double(meridianCount)),&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                            green: &lt;span style=&#34;color:#f5a97f&#34;&gt;0.3&lt;/span&gt;,&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//(Double(i)/Double(parallelCount)),&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                            blue: (&lt;span style=&#34;color:#91d7e3&#34;&gt;Double&lt;/span&gt;(i)&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;/&lt;/span&gt;&lt;span style=&#34;color:#91d7e3&#34;&gt;Double&lt;/span&gt;(parallelCount))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                        )
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                        .translateBy(findCoordinate_dy(parallel: i, meridian: j))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//Assumptions: &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// - Y is up, &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// - polar value is inflection up to Y. &amp;lt;==== THIS IS WRONG!!!&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;findCoordinate_dy&lt;/span&gt;(parallel:&lt;span style=&#34;color:#91d7e3&#34;&gt;Int&lt;/span&gt;, meridian:&lt;span style=&#34;color:#91d7e3&#34;&gt;Int&lt;/span&gt;) -&amp;gt; Vector {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;polarAngle&lt;/span&gt; = asin(&lt;span style=&#34;color:#f5a97f&#34;&gt;1&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;-&lt;/span&gt;&lt;span style=&#34;color:#91d7e3&#34;&gt;Double&lt;/span&gt;(parallel) &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;*&lt;/span&gt; base_lat_dy)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;azimuthal&lt;/span&gt; = &lt;span style=&#34;color:#91d7e3&#34;&gt;Double&lt;/span&gt;(meridian) &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;*&lt;/span&gt; base_long_dphi
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// print(&amp;#34;y: \(Double(parallel) * base_lat_dy)&amp;#34;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// print(&amp;#34;polar angle:\(polarAngle), azimuthal:\(azimuthal)&amp;#34;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;y&lt;/span&gt; = sin(polarAngle)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;x&lt;/span&gt; = cos(polarAngle) &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;*&lt;/span&gt; cos(azimuthal)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;z&lt;/span&gt; = cos(polarAngle) &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;*&lt;/span&gt; sin(azimuthal)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//print(x, y, z)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; Vector(x: x, y: y, z: z).scaled(by: radius)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;findCoordinate_dtheta&lt;/span&gt;(parallel:&lt;span style=&#34;color:#91d7e3&#34;&gt;Int&lt;/span&gt;, meridian:&lt;span style=&#34;color:#91d7e3&#34;&gt;Int&lt;/span&gt;) -&amp;gt; Vector {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;polarAngle&lt;/span&gt; = &lt;span style=&#34;color:#91d7e3&#34;&gt;Double&lt;/span&gt;.pi &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;/&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;2&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;-&lt;/span&gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;Double&lt;/span&gt;(parallel) &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;*&lt;/span&gt; base_polar_deflection
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;azimuthal&lt;/span&gt; = &lt;span style=&#34;color:#91d7e3&#34;&gt;Double&lt;/span&gt;(meridian) &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;*&lt;/span&gt; base_long_dphi
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;polar angle:&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;polarAngle&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;, azimuthal:&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;azimuthal&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;y&lt;/span&gt; = sin(polarAngle)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;x&lt;/span&gt; = cos(polarAngle) &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;*&lt;/span&gt; cos(azimuthal)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;z&lt;/span&gt; = cos(polarAngle) &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;*&lt;/span&gt; sin(azimuthal)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(x, y, z)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; Vector(x: x, y: y, z: z).scaled(by: radius)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This code works, but has a conceptual mistake in it that I may have made in some of my code yesterday. Generally the polar angle is meant to be deflection DOWN from vertical, not up from the azimuth.  That would be an elevation angle. It&amp;rsquo;s fine to use an elevation angle, but that&amp;rsquo;s not what I&amp;rsquo;ve been calling it.  I re-wrote the code to be more inline with what &lt;a href=&#34;https://en.wikipedia.org/wiki/Spherical_coordinate_system&#34;&gt;Wikipedia says&lt;/a&gt; the &lt;a href=&#34;https://www.iso.org/standard/64973.html&#34;&gt;ISO standard&lt;/a&gt; says.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//Polar Angle is deflection down, not inflection up.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//Y is up.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;findCoordinate_dy&lt;/span&gt;(parallel:&lt;span style=&#34;color:#91d7e3&#34;&gt;Int&lt;/span&gt;, meridian:&lt;span style=&#34;color:#91d7e3&#34;&gt;Int&lt;/span&gt;) -&amp;gt; Vector {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;polarAngle&lt;/span&gt; = acos(&lt;span style=&#34;color:#f5a97f&#34;&gt;1&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;-&lt;/span&gt;&lt;span style=&#34;color:#91d7e3&#34;&gt;Double&lt;/span&gt;(parallel) &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;*&lt;/span&gt; base_lat_dy)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;azimuthal&lt;/span&gt; = &lt;span style=&#34;color:#91d7e3&#34;&gt;Double&lt;/span&gt;(meridian) &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;*&lt;/span&gt; base_long_dphi
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// print(&amp;#34;y: \(Double(parallel) * base_lat_dy)&amp;#34;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// print(&amp;#34;polar angle:\(polarAngle), azimuthal:\(azimuthal)&amp;#34;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;sin_polar&lt;/span&gt; = sin(polarAngle)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;x&lt;/span&gt; = sin_polar &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;*&lt;/span&gt; cos(azimuthal)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;y&lt;/span&gt; = cos(polarAngle)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;z&lt;/span&gt; = sin_polar &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;*&lt;/span&gt; sin(azimuthal)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//print(x, y, z)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; Vector(x: x, y: y, z: z).scaled(by: radius)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;findCoordinate_dtheta&lt;/span&gt;(parallel:&lt;span style=&#34;color:#91d7e3&#34;&gt;Int&lt;/span&gt;, meridian:&lt;span style=&#34;color:#91d7e3&#34;&gt;Int&lt;/span&gt;) -&amp;gt; Vector {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;polarAngle&lt;/span&gt; = &lt;span style=&#34;color:#91d7e3&#34;&gt;Double&lt;/span&gt;(parallel) &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;*&lt;/span&gt; base_polar_deflection
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;azimuthal&lt;/span&gt; = &lt;span style=&#34;color:#91d7e3&#34;&gt;Double&lt;/span&gt;(meridian) &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;*&lt;/span&gt; base_long_dphi
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//print(&amp;#34;polar angle:\(polarAngle), azimuthal:\(azimuthal)&amp;#34;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;sin_polar&lt;/span&gt; = sin(polarAngle)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;x&lt;/span&gt; = sin_polar &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;*&lt;/span&gt; cos(azimuthal)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;y&lt;/span&gt; = cos(polarAngle)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;z&lt;/span&gt; = sin_polar &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;*&lt;/span&gt; sin(azimuthal)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//print(x, y, z)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; Vector(x: x, y: y, z: z).scaled(by: radius)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;I also added a coordinate conversion pair.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;MARK:&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt; Coordinate conversion. matched set.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//Assumes Y is up. Polar coord is deflection down. &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;sphericalCoordinate&lt;/span&gt;(to:Vector, from:Vector = Vector(x: &lt;span style=&#34;color:#f5a97f&#34;&gt;0&lt;/span&gt;, y: &lt;span style=&#34;color:#f5a97f&#34;&gt;0&lt;/span&gt;, z: &lt;span style=&#34;color:#f5a97f&#34;&gt;0&lt;/span&gt;)) -&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    (radius:&lt;span style=&#34;color:#91d7e3&#34;&gt;Double&lt;/span&gt;, polar:&lt;span style=&#34;color:#91d7e3&#34;&gt;Double&lt;/span&gt;, azimuthal:&lt;span style=&#34;color:#91d7e3&#34;&gt;Double&lt;/span&gt;){
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;dx&lt;/span&gt; = to.x&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;-&lt;/span&gt;from.x
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;dy&lt;/span&gt; = to.y&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;-&lt;/span&gt;from.y
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;dz&lt;/span&gt; = to.z&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;-&lt;/span&gt;from.z
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;v_radius&lt;/span&gt; = (dx&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;*&lt;/span&gt;dx &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;+&lt;/span&gt; dy&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;*&lt;/span&gt;dy &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;+&lt;/span&gt; dz&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;*&lt;/span&gt;dz).squareRoot()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;polar&lt;/span&gt; = acos(dy&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;/&lt;/span&gt;v_radius); &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//theta&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;azimuthal&lt;/span&gt; = atan(dz&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;/&lt;/span&gt;dx); &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//phi&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; (v_radius, polar, azimuthal)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;cartesianCoordinate&lt;/span&gt;(polar:&lt;span style=&#34;color:#91d7e3&#34;&gt;Double&lt;/span&gt;, azimuthal:&lt;span style=&#34;color:#91d7e3&#34;&gt;Double&lt;/span&gt;, radius:&lt;span style=&#34;color:#91d7e3&#34;&gt;Double&lt;/span&gt; = &lt;span style=&#34;color:#f5a97f&#34;&gt;1&lt;/span&gt;) -&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    Vector {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;sin_polar&lt;/span&gt; = sin(polar)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;x&lt;/span&gt; = sin_polar &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;*&lt;/span&gt; cos(azimuthal)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;y&lt;/span&gt; = cos(polar)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;z&lt;/span&gt; = sin_polar &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;*&lt;/span&gt; sin(azimuthal)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; Vector(x: x, y: y, z: z).scaled(by: &lt;span style=&#34;color:#f5a97f&#34;&gt;1&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;I&amp;rsquo;ll probably add these to the Vector type down the line.&lt;/p&gt;
&lt;h2 id=&#34;no-repeat-spheres&#34;&gt;No repeat spheres&lt;/h2&gt;
&lt;p&gt;The poles have a lot of &lt;code&gt;Spheres&lt;/code&gt; all stacked up in one place. I made a simplistic &amp;ldquo;only unique spheres&amp;rdquo; validation by adding a coordinateSet to my build function. The Sphere will only draw if the coordinates proposed are novel.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;buildStage&lt;/span&gt;() -&amp;gt; Canvas3D {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//Vector conforms to Hashable. &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;coordinateSet&lt;/span&gt;:Set&amp;lt;Vector&amp;gt; = []
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; Canvas3D {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;for&lt;/span&gt; i &lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;0.&lt;/span&gt;.&amp;lt;parallelCount {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#c6a0f6&#34;&gt;for&lt;/span&gt; j &lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;0.&lt;/span&gt;.&amp;lt;meridianCount {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    makeSphere(parallel: i, meridian: j)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;makeSphere&lt;/span&gt;(parallel: &lt;span style=&#34;color:#91d7e3&#34;&gt;Int&lt;/span&gt;, meridian: &lt;span style=&#34;color:#91d7e3&#34;&gt;Int&lt;/span&gt;) -&amp;gt; Sphere? {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;coords&lt;/span&gt; = findCoordinate_dtheta(parallel: parallel, meridian: meridian)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;result&lt;/span&gt; = coordinateSet.&lt;span style=&#34;color:#91d7e3&#34;&gt;insert&lt;/span&gt;(coords)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; result.inserted {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; Sphere(radius: sphere_radius)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    .color(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                        red: &lt;span style=&#34;color:#f5a97f&#34;&gt;0.3&lt;/span&gt;, &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//(Double(j)/Double(meridianCount)),&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                        green: &lt;span style=&#34;color:#f5a97f&#34;&gt;0.3&lt;/span&gt;,&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//(Double(i)/Double(parallelCount)),&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                        blue: (&lt;span style=&#34;color:#91d7e3&#34;&gt;Double&lt;/span&gt;(parallel)&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;/&lt;/span&gt;&lt;span style=&#34;color:#91d7e3&#34;&gt;Double&lt;/span&gt;(parallelCount))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    )
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    .translateBy(coords)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;nil&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Also, added to &lt;code&gt;Canvas3DBuilder&lt;/code&gt; to handle the optional &lt;code&gt;Sphere&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;enum&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;Canvas3DBuilder&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;buildExpression&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; expression: Sphere?) -&amp;gt; [Sphere] {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;expression&lt;/span&gt; { &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; [expression] }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;else&lt;/span&gt; { &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; [] }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;My usd file went down from 1115 lines to 1016, which is some good savings.&lt;/p&gt;
&lt;h2 id=&#34;references&#34;&gt;References&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;http://www.songho.ca/opengl/gl_sphere.html&#34;&gt;http://www.songho.ca/opengl/gl_sphere.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://stackoverflow.com/questions/5674149/3d-coordinates-on-a-sphere-to-latitude-and-longitude&#34;&gt;https://stackoverflow.com/questions/5674149/3d-coordinates-on-a-sphere-to-latitude-and-longitude&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</description>
    </item>
    
    
    
    <item>
      <title>Hello USD - Part 18: I can make a sphere out of Spheres!</title>
      <link>https://whynotestflight.com/excuses/hello-usd-part-18-i-can-make-a-sphere-out-of-spheres/</link>
      <pubDate>Wed, 26 Jul 2023 00:00:00 +0000</pubDate>
      
      <guid>https://whynotestflight.com/excuses/hello-usd-part-18-i-can-make-a-sphere-out-of-spheres/</guid>
      <description>&lt;script type=&#39;text/javascript&#39; src=&#39;https://www.x3dom.org/download/x3dom.js&#39;&gt; &lt;/script&gt; 
&lt;p&gt;After all the refactoring and waiting, I needed some playtime with &lt;a href=&#34;https://github.com/carlynorama/SketchPad&#34;&gt;SketchPad&lt;/a&gt; just the way it is for a moment.  Get a feel for how working with it compares to something like &lt;a href=&#34;https://p5js.org&#34;&gt;p5js&lt;/a&gt; or &lt;a href=&#34;https://processingfoundation.org&#34;&gt;Processing&lt;/a&gt;. Nice thing about the X3D files is I can embed them directly in the page. Some day &lt;code&gt;.usda&lt;/code&gt;, some day&amp;hellip;&lt;/p&gt;
&lt;p&gt;UPDATE: In some of the code below I refer to angles of elevation as &lt;code&gt;polar&lt;/code&gt;, which is not correct.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;If the up-axis coordinate is determined by &lt;code&gt;sin(some_angle)&lt;/code&gt;, that angle is an elevation, up from the azimuth&lt;/li&gt;
&lt;li&gt;If the up-axis coordinate is determined by a &lt;code&gt;cos(some_angle)&lt;/code&gt;, it is in fact polar, i.e. displacement &amp;ldquo;downward&amp;rdquo;, away from, the primary axis.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;make-a-ring&#34;&gt;Make a Ring&lt;/h2&gt;
&lt;p&gt;First I made a ring, because I&amp;rsquo;ve &lt;a href=&#34;https://carlynorama.github.io/2023January-30DaysNatureOfCode/12-circular-motion/&#34;&gt;made those before&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;In the ring code I used a single and and a distance angle to create 2 coordinates, basic &lt;a href=&#34;https://www.khanacademy.org/computing/computer-programming/programming-natural-simulations/programming-angular-movement/a/polar-coordinates&#34;&gt;polar coordinate to cartesian conversion&lt;/a&gt;.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;theta&lt;/span&gt; = base_theta &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;*&lt;/span&gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;Double&lt;/span&gt;(i) 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;x&lt;/span&gt; = cos(theta) &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;*&lt;/span&gt; radius
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;y&lt;/span&gt; = sin(theta) &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;*&lt;/span&gt; radius
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;Ring(count:18, radius: 12).buildStage()&lt;/code&gt;&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;Ring&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;init&lt;/span&gt;(&lt;span style=&#34;color:#91d7e3&#34;&gt;count&lt;/span&gt;:&lt;span style=&#34;color:#91d7e3&#34;&gt;Int&lt;/span&gt;, radius:&lt;span style=&#34;color:#91d7e3&#34;&gt;Double&lt;/span&gt;, ratio:&lt;span style=&#34;color:#91d7e3&#34;&gt;Double&lt;/span&gt; = &lt;span style=&#34;color:#f5a97f&#34;&gt;0.1&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;.&lt;span style=&#34;color:#91d7e3&#34;&gt;count&lt;/span&gt; = &lt;span style=&#34;color:#91d7e3&#34;&gt;count&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;.radius = radius
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;.ratio = ratio
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;count&lt;/span&gt;:&lt;span style=&#34;color:#91d7e3&#34;&gt;Int&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;radius&lt;/span&gt;:&lt;span style=&#34;color:#91d7e3&#34;&gt;Double&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;ratio&lt;/span&gt;:&lt;span style=&#34;color:#91d7e3&#34;&gt;Double&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;tau&lt;/span&gt; = &lt;span style=&#34;color:#91d7e3&#34;&gt;Double&lt;/span&gt;.pi &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;*&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;2&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;buildStage&lt;/span&gt;() -&amp;gt; Canvas3D {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//the change between each sphere based on the number &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//wanted in the ring. &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;base_theta&lt;/span&gt; = tau&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;/&lt;/span&gt;&lt;span style=&#34;color:#91d7e3&#34;&gt;Double&lt;/span&gt;(&lt;span style=&#34;color:#91d7e3&#34;&gt;count&lt;/span&gt;) 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;sphere_radius&lt;/span&gt; = radius&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;*&lt;/span&gt;ratio
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; Canvas3D {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            Sphere(radius: sphere_radius).color(red: &lt;span style=&#34;color:#f5a97f&#34;&gt;0.18&lt;/span&gt;, green: &lt;span style=&#34;color:#f5a97f&#34;&gt;0.18&lt;/span&gt;, blue: &lt;span style=&#34;color:#f5a97f&#34;&gt;0.18&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;             &lt;span style=&#34;color:#c6a0f6&#34;&gt;for&lt;/span&gt; i &lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;0.&lt;/span&gt;.&amp;lt;&lt;span style=&#34;color:#91d7e3&#34;&gt;count&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                 &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;theta&lt;/span&gt; = base_theta &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;*&lt;/span&gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;Double&lt;/span&gt;(i) 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                 &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;x&lt;/span&gt; = cos(theta) &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;*&lt;/span&gt; radius
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                 &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;y&lt;/span&gt; = sin(theta) &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;*&lt;/span&gt; radius
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                 Sphere(radius: sphere_radius)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                 .color(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                     red: sin(theta),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                     green: &lt;span style=&#34;color:#f5a97f&#34;&gt;0.2&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                     blue: cos(theta)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                 )
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                 .translateBy(Vector(x: x, y: y, z: &lt;span style=&#34;color:#f5a97f&#34;&gt;0.0&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;             }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;a href=&#34;final_ring_20230725T092512.usda&#34;&gt;ring usda file&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;final_ring.png&#34; alt=&#34;Screen shot of a ring made out of 18 spheres in a mid-tone rainbow color scheme&#34;&gt;&lt;/p&gt;
&lt;h2 id=&#34;random-shell&#34;&gt;Random Shell&lt;/h2&gt;
&lt;p&gt;The real trick is is to make a sphere.&lt;/p&gt;
&lt;p&gt;A ring is simply a special case of &lt;a href=&#34;https://en.wikipedia.org/wiki/Spherical_coordinate_system&#34;&gt;spherical coordinates&lt;/a&gt; where the second, azimuthal, angle stays at zero.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;theta&lt;/span&gt; = base_theta &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;*&lt;/span&gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;Double&lt;/span&gt;(i)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;phi&lt;/span&gt; = &lt;span style=&#34;color:#f5a97f&#34;&gt;0&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//cos(phi) == 1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;x&lt;/span&gt; = cos(theta) &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;*&lt;/span&gt; cos(phi) &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;*&lt;/span&gt; radius
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;y&lt;/span&gt; = sin(theta) &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;*&lt;/span&gt; cos(phi) &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;*&lt;/span&gt; radius
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//sin(phi) == 0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;z&lt;/span&gt; = sin(phi)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This means, to make a shell of randomly placed spheres doesn&amp;rsquo;t require a whole lot of extra code over just making a ring.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//  RandomShell.swift&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//  &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//  Created by Carlyn Maw on 7/25/23.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;Foundation&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//https://en.wikipedia.org/wiki/Sphere&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;RandomShell&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;init&lt;/span&gt;(&lt;span style=&#34;color:#91d7e3&#34;&gt;count&lt;/span&gt;:&lt;span style=&#34;color:#91d7e3&#34;&gt;Int&lt;/span&gt;, radius:&lt;span style=&#34;color:#91d7e3&#34;&gt;Double&lt;/span&gt;, ratio:&lt;span style=&#34;color:#91d7e3&#34;&gt;Double&lt;/span&gt; = &lt;span style=&#34;color:#f5a97f&#34;&gt;0.1&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;.&lt;span style=&#34;color:#91d7e3&#34;&gt;count&lt;/span&gt; = &lt;span style=&#34;color:#91d7e3&#34;&gt;count&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;.radius = radius
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;.ratio = ratio
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;count&lt;/span&gt;:&lt;span style=&#34;color:#91d7e3&#34;&gt;Int&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;radius&lt;/span&gt;:&lt;span style=&#34;color:#91d7e3&#34;&gt;Double&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;ratio&lt;/span&gt;:&lt;span style=&#34;color:#91d7e3&#34;&gt;Double&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;tau&lt;/span&gt; = &lt;span style=&#34;color:#91d7e3&#34;&gt;Double&lt;/span&gt;.pi &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;*&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;2&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;π&lt;/span&gt; = &lt;span style=&#34;color:#91d7e3&#34;&gt;Double&lt;/span&gt;.pi
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;buildStage&lt;/span&gt;() -&amp;gt; Canvas3D {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;sun_color&lt;/span&gt; = &lt;span style=&#34;color:#f5a97f&#34;&gt;0.9&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;sphere_radius&lt;/span&gt; = radius&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;*&lt;/span&gt;ratio
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; Canvas3D {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            Sphere(radius: sphere_radius).color(red: sun_color, green: sun_color, blue: sun_color)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;             &lt;span style=&#34;color:#c6a0f6&#34;&gt;for&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;0.&lt;/span&gt;.&amp;lt;&lt;span style=&#34;color:#91d7e3&#34;&gt;count&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                 &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;theta&lt;/span&gt; = &lt;span style=&#34;color:#91d7e3&#34;&gt;Double&lt;/span&gt;.random(&lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt;: &lt;span style=&#34;color:#f5a97f&#34;&gt;0.&lt;/span&gt;..&lt;span style=&#34;color:#ed8796&#34;&gt;π&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                 &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;phi&lt;/span&gt; = &lt;span style=&#34;color:#91d7e3&#34;&gt;Double&lt;/span&gt;.random(&lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt;: &lt;span style=&#34;color:#f5a97f&#34;&gt;0.&lt;/span&gt;..tau)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                 &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;x&lt;/span&gt; = radius &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;*&lt;/span&gt; sin(theta) &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;*&lt;/span&gt; cos(phi)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                 &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;y&lt;/span&gt; = radius &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;*&lt;/span&gt; sin(theta) &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;*&lt;/span&gt; sin(phi)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                 &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;z&lt;/span&gt; = radius &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;*&lt;/span&gt; cos(theta)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                 Sphere(radius: sphere_radius)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                 .color(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    red: cos(phi).magnitude,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                     green: cos(theta).magnitude,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    blue: sin(phi).magnitude
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                 )
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                 .translateBy(Vector(x: x, y: y, z: z))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;             }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;a href=&#34;content/posts/20230725-hello-usd-pt18-spheres/random_shell_20230725T163232.usda&#34;&gt;random shell usda file&lt;/a&gt;&lt;/p&gt;
&lt;x3d width=&#39;500px&#39; height=&#39;400px&#39;&gt; 
&lt;scene&gt;
&lt;viewpoint position=&#34;0 0 50&#34;&gt;&lt;/viewpoint&gt;
&lt;inline url=&#34;random_shell_20230725T163232.x3d&#34;&gt; &lt;/inline&gt; 
&lt;/scene&gt; 
&lt;/x3d&gt; 
&lt;h2 id=&#34;precisely-placed-item&#34;&gt;Precisely placed item&lt;/h2&gt;
&lt;p&gt;Creating a randomly placed sphere in the shell doesn&amp;rsquo;t require understanding the coordinate system because no matter which way is up, or forward, or back, it will still look like a sphere.&lt;/p&gt;
&lt;p&gt;Having actual control over placement in space requires understanding the coordinate system.&lt;/p&gt;
&lt;p&gt;I made two different functions for placing an item using spherical coordinates.&lt;/p&gt;
&lt;p&gt;The first follows the classic physics model.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Z is up&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;X is towards the front&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Y is to the right&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Can be expressed as (r, θ, φ)&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;radial distance
&lt;ul&gt;
&lt;li&gt;r ≥ 0,&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;polar angle (theta):
&lt;ul&gt;
&lt;li&gt;0° ≤ θ ≤ 180° (π rad)&lt;/li&gt;
&lt;li&gt;also referred to as inclination/elevation)&lt;/li&gt;
&lt;li&gt;Positive is from z towards y (left handed/cw when thumb is x)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;azimuth (phi)
&lt;ul&gt;
&lt;li&gt;0° ≤ φ &amp;lt; 360° (2π rad).&lt;/li&gt;
&lt;li&gt;Positive is from x towards y (right handed/ccw, when thumb is z)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src=&#34;3D_Spherical_edited.svg&#34; alt=&#34;Illustration of a 3D spherical coordinate system&#34;&gt;&lt;/p&gt;
&lt;p&gt;Derivative of image by Andeggs - Own work, Public Domain, &lt;a href=&#34;https://commons.wikimedia.org/w/index.php?curid=7478049&#34;&gt;https://commons.wikimedia.org/w/index.php?curid=7478049&lt;/a&gt;&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;sphericalCoordinate&lt;/span&gt;(theta:&lt;span style=&#34;color:#91d7e3&#34;&gt;Double&lt;/span&gt;, phi:&lt;span style=&#34;color:#91d7e3&#34;&gt;Double&lt;/span&gt;) -&amp;gt; Vector {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;sin_theta&lt;/span&gt; = sin(theta)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;x&lt;/span&gt; = sin_theta &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;*&lt;/span&gt; cos(phi)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;y&lt;/span&gt; = sin_theta &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;*&lt;/span&gt; sin(phi)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;z&lt;/span&gt; = cos(theta)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; Vector(x: x, y: y, z: z)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The second, very similar function, tries to create more intuitive behavior in the OpenUSD/X3D coordinate system with &amp;ldquo;Y&amp;rdquo; set as the Up Axis, which is common.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Y is up&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Z is towards the front&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;X is to the right&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;xyPlane&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;polar plane&lt;/li&gt;
&lt;li&gt;positive number moves item up/clockwise&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;xzPlane&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;azimuthal&lt;/li&gt;
&lt;li&gt;positive number moves item forward/clockwise&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;sphericalCoordinate&lt;/span&gt;(xyPlane:&lt;span style=&#34;color:#91d7e3&#34;&gt;Double&lt;/span&gt;, xzPlane:&lt;span style=&#34;color:#91d7e3&#34;&gt;Double&lt;/span&gt;) -&amp;gt; Vector {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;cos_xz&lt;/span&gt; = cos(xzPlane)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;x&lt;/span&gt; = cos_xz &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;*&lt;/span&gt; cos(xyPlane)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;y&lt;/span&gt; = cos_xz &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;*&lt;/span&gt; sin(xyPlane)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;z&lt;/span&gt; = sin(xzPlane)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; Vector(x: x, y: y, z: z)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Placed in the context of Axis layout:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;AxisWithSpheres&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;init&lt;/span&gt;(&lt;span style=&#34;color:#91d7e3&#34;&gt;count&lt;/span&gt;:&lt;span style=&#34;color:#91d7e3&#34;&gt;Int&lt;/span&gt;, radius:&lt;span style=&#34;color:#91d7e3&#34;&gt;Double&lt;/span&gt;, ratio:&lt;span style=&#34;color:#91d7e3&#34;&gt;Double&lt;/span&gt; = &lt;span style=&#34;color:#f5a97f&#34;&gt;0.1&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;.&lt;span style=&#34;color:#91d7e3&#34;&gt;count&lt;/span&gt; = &lt;span style=&#34;color:#91d7e3&#34;&gt;count&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;.radius = radius
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;.ratio = ratio
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;count&lt;/span&gt;:&lt;span style=&#34;color:#91d7e3&#34;&gt;Int&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;radius&lt;/span&gt;:&lt;span style=&#34;color:#91d7e3&#34;&gt;Double&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;ratio&lt;/span&gt;:&lt;span style=&#34;color:#91d7e3&#34;&gt;Double&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;π&lt;/span&gt; = &lt;span style=&#34;color:#91d7e3&#34;&gt;Double&lt;/span&gt;.pi
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;buildStage&lt;/span&gt;() -&amp;gt; Canvas3D {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;stride&lt;/span&gt; = radius&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;/&lt;/span&gt;&lt;span style=&#34;color:#91d7e3&#34;&gt;Double&lt;/span&gt;(&lt;span style=&#34;color:#91d7e3&#34;&gt;count&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;sphere_radius&lt;/span&gt; = &lt;span style=&#34;color:#91d7e3&#34;&gt;stride&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;*&lt;/span&gt; ratio
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;r&lt;/span&gt; = radius&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;/&lt;/span&gt;&lt;span style=&#34;color:#f5a97f&#34;&gt;2&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;polar&lt;/span&gt; = &lt;span style=&#34;color:#ed8796&#34;&gt;π&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;/&lt;/span&gt;&lt;span style=&#34;color:#f5a97f&#34;&gt;4&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;azimuthal&lt;/span&gt; = &lt;span style=&#34;color:#ed8796&#34;&gt;π&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;/&lt;/span&gt;&lt;span style=&#34;color:#f5a97f&#34;&gt;8&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; Canvas3D {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            Sphere(radius: sphere_radius&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;*&lt;/span&gt;&lt;span style=&#34;color:#f5a97f&#34;&gt;3&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                .color(red: &lt;span style=&#34;color:#f5a97f&#34;&gt;0.1&lt;/span&gt;, green: &lt;span style=&#34;color:#f5a97f&#34;&gt;0.8&lt;/span&gt;, blue: &lt;span style=&#34;color:#f5a97f&#34;&gt;1&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                .translateBy(sphericalCoordinate(xyPlane: polar, xzPlane: azimuthal).scaled(by: r))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            Sphere(radius: sphere_radius&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;*&lt;/span&gt;&lt;span style=&#34;color:#f5a97f&#34;&gt;3&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                .color(red: &lt;span style=&#34;color:#f5a97f&#34;&gt;1&lt;/span&gt;, green: &lt;span style=&#34;color:#f5a97f&#34;&gt;0.8&lt;/span&gt;, blue: &lt;span style=&#34;color:#f5a97f&#34;&gt;0.1&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                .translateBy(sphericalCoordinate(theta: polar, phi: azimuthal).scaled(by: r))  
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//Axis --------------------------------  &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;for&lt;/span&gt; i &lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;0.&lt;/span&gt;..&lt;span style=&#34;color:#91d7e3&#34;&gt;count&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                Sphere(radius: sphere_radius)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    .color(red: &lt;span style=&#34;color:#f5a97f&#34;&gt;1&lt;/span&gt;, green: &lt;span style=&#34;color:#f5a97f&#34;&gt;0&lt;/span&gt;, blue: &lt;span style=&#34;color:#f5a97f&#34;&gt;0&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    .translateBy(Vector(x: &lt;span style=&#34;color:#91d7e3&#34;&gt;Double&lt;/span&gt;(i)&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;*&lt;/span&gt;&lt;span style=&#34;color:#91d7e3&#34;&gt;stride&lt;/span&gt;, y: &lt;span style=&#34;color:#f5a97f&#34;&gt;0&lt;/span&gt;, z: &lt;span style=&#34;color:#f5a97f&#34;&gt;0&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;for&lt;/span&gt; i &lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;0.&lt;/span&gt;..&lt;span style=&#34;color:#91d7e3&#34;&gt;count&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                Sphere(radius: sphere_radius)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    .color(red: &lt;span style=&#34;color:#f5a97f&#34;&gt;0&lt;/span&gt;, green: &lt;span style=&#34;color:#f5a97f&#34;&gt;1&lt;/span&gt;, blue: &lt;span style=&#34;color:#f5a97f&#34;&gt;0&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    .translateBy(Vector(x: &lt;span style=&#34;color:#f5a97f&#34;&gt;0&lt;/span&gt;, y: &lt;span style=&#34;color:#91d7e3&#34;&gt;Double&lt;/span&gt;(i)&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;*&lt;/span&gt;&lt;span style=&#34;color:#91d7e3&#34;&gt;stride&lt;/span&gt;, z: &lt;span style=&#34;color:#f5a97f&#34;&gt;0&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;for&lt;/span&gt; i &lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;0.&lt;/span&gt;..&lt;span style=&#34;color:#91d7e3&#34;&gt;count&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                Sphere(radius: sphere_radius)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    .color(red: &lt;span style=&#34;color:#f5a97f&#34;&gt;0&lt;/span&gt;, green: &lt;span style=&#34;color:#f5a97f&#34;&gt;0&lt;/span&gt;, blue: &lt;span style=&#34;color:#f5a97f&#34;&gt;1&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    .translateBy(Vector(x: &lt;span style=&#34;color:#f5a97f&#34;&gt;0&lt;/span&gt;, y: &lt;span style=&#34;color:#f5a97f&#34;&gt;0&lt;/span&gt;, z: &lt;span style=&#34;color:#91d7e3&#34;&gt;Double&lt;/span&gt;(i)&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;*&lt;/span&gt;&lt;span style=&#34;color:#91d7e3&#34;&gt;stride&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Yellow placed with physics-math. Pale blue placed with the 3DGraphics coordinate system friendly function. Same angles but different axis orientation means entirely different locations.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;axis_plus_spheres_20230725T155041.usda&#34;&gt;axis_plus_spheres usda file&lt;/a&gt;&lt;/p&gt;
&lt;x3d width=&#39;500px&#39; height=&#39;400px&#39;&gt; 
&lt;scene&gt;
&lt;viewpoint position=&#34;0 5 30&#34;&gt;&lt;/viewpoint&gt;
&lt;inline url=&#34;axis_plus_spheres_20230725T155041.x3d&#34;&gt; &lt;/inline&gt; 
&lt;/scene&gt; 
&lt;/x3d&gt;
&lt;h2 id=&#34;spiral-distribution&#34;&gt;Spiral Distribution&lt;/h2&gt;
&lt;p&gt;The ring represents an even distribution around a circle. But what is an even distribution around a sphere? A common choice is the Fibonacci Spiral.&lt;/p&gt;
&lt;p&gt;Unfortunately the variable phi, commonly used for the &lt;a href=&#34;https://en.wikipedia.org/wiki/Golden_ratio&#34;&gt;golden ratio&lt;/a&gt;, is already in use for azimuths, so I&amp;rsquo;ll just call it &lt;code&gt;goldenRatio&lt;/code&gt;. In fact, I will try avoid it in sphere talk as well because Mathematicians and Physicists apparently swap theta and phi around, because of course they do.&lt;/p&gt;
&lt;h3 id=&#34;version-1&#34;&gt;Version 1&lt;/h3&gt;
&lt;p&gt;A popular answer on &lt;a href=&#34;https://stackoverflow.com/a/26127012/5946596&#34;&gt;StackOverflow&lt;/a&gt; uses &lt;a href=&#34;https://arxiv.org/pdf/0912.4540.pdf&#34;&gt;a paper by Álvaro Gonzálezto&lt;/a&gt; as the basis of its python code.&lt;/p&gt;
&lt;p&gt;I reworked it like this:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;goldenAngle&lt;/span&gt; = &lt;span style=&#34;color:#91d7e3&#34;&gt;Double&lt;/span&gt;.pi &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;*&lt;/span&gt; (&lt;span style=&#34;color:#f5a97f&#34;&gt;3&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;-&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;5.0&lt;/span&gt;).squareRoot())
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//&amp;#34;Top&amp;#34;, (low) indices, start at max Y. Spiral is around Y axis&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;generatePoints_SOV1&lt;/span&gt;(&lt;span style=&#34;color:#91d7e3&#34;&gt;count&lt;/span&gt;:&lt;span style=&#34;color:#91d7e3&#34;&gt;Int&lt;/span&gt;, radius:&lt;span style=&#34;color:#91d7e3&#34;&gt;Double&lt;/span&gt;) -&amp;gt; [Vector] {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;points&lt;/span&gt;:[Vector] = []
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;for&lt;/span&gt; i &lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;1.&lt;/span&gt;.&amp;lt;&lt;span style=&#34;color:#91d7e3&#34;&gt;count&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//pick a Y value in the domain of the unit circle (-1, 1)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//based on a percentage of how far into the the count we are&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;sin_polar&lt;/span&gt;:&lt;span style=&#34;color:#91d7e3&#34;&gt;Double&lt;/span&gt; = &lt;span style=&#34;color:#f5a97f&#34;&gt;1&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;-&lt;/span&gt; (&lt;span style=&#34;color:#91d7e3&#34;&gt;Double&lt;/span&gt;(i) &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;/&lt;/span&gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;Double&lt;/span&gt;(&lt;span style=&#34;color:#91d7e3&#34;&gt;count&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;-&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;1&lt;/span&gt;)) &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;*&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;2&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//√(c^2 - b^2) = a, in the stack overflow code they call this a radius&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//More specifically its the cos the angle in the plane of y and x,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//which gives us the radius of the circular slice in the perpendicular plane&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//that x and z will be on.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;cos_polar&lt;/span&gt; = (&lt;span style=&#34;color:#f5a97f&#34;&gt;1.0&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;-&lt;/span&gt; sin_polar &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;*&lt;/span&gt; sin_polar).squareRoot()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//Used actual golden angle, the SO answer uses the compliment&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//for a different winding.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;azimuthal&lt;/span&gt; = goldenAngle &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;*&lt;/span&gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;Double&lt;/span&gt;(i)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//since we picked Y to be our index axis, what&amp;#39;s left is x and z&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//They complement each other (sin,cos pair), but get tilted by the original&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;x&lt;/span&gt; = cos(azimuthal) &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;*&lt;/span&gt; cos_polar
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;z&lt;/span&gt; = sin(azimuthal) &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;*&lt;/span&gt; cos_polar
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;y&lt;/span&gt; = sin_polar &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//the up is the lonely one.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//Code could potentially apply the scaling to the points afterwards&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//en masse and in parallel. Not an issue at this point.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            points.append(Vector(x: x, y: y, z: z).scaled(by: radius))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; points
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The code works much like the &lt;code&gt;sphericalCoordinate(xyPlane:Double, xzPlane:Double)&lt;/code&gt; function, but it leads with a y-value with a known distance from the center (it&amp;rsquo;s a &lt;a href=&#34;https://en.wikipedia.org/wiki/Unit_sphere&#34;&gt;unit sphere&lt;/a&gt;) to calculate the polar-angle and uses the goldenAngle combined with the index number to generate an azimuthal value.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;spiralv1_20230725T183213.usda&#34;&gt;spiralv1 usda file&lt;/a&gt;&lt;/p&gt;
&lt;x3d width=&#39;500px&#39; height=&#39;400px&#39;&gt; 
&lt;scene&gt;
&lt;viewpoint position=&#34;0 0 50&#34;&gt;&lt;/viewpoint&gt;
&lt;inline url=&#34;spiralv1_20230725T183213.x3d&#34;&gt; &lt;/inline&gt; 
&lt;/scene&gt; 
&lt;/x3d&gt; 
&lt;h3 id=&#34;version-2&#34;&gt;Version 2&lt;/h3&gt;
&lt;p&gt;A &lt;a href=&#34;https://stackoverflow.com/a/44164075/5946596&#34;&gt;second popular answer&lt;/a&gt; works similarly, but has a slightly nicer wrapping &lt;a href=&#34;https://extremelearning.com.au/how-to-evenly-distribute-points-on-a-sphere-more-effectively-than-the-canonical-fibonacci-lattice/&#34;&gt;due to an offset suggested by its source&lt;/a&gt;. The article and code use Mathematics notation rather than physics notation; the theta and phi are swapped from how I used them earlier. I left out those symbols and used &amp;ldquo;polar&amp;rdquo; and &amp;ldquo;azimuthal&amp;rdquo; for clarity.&lt;/p&gt;
&lt;p&gt;Also, as originally written, it grows along the Z axis. I put the Y axis winding code in but left it commented out.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;     &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//&amp;#34;Top&amp;#34;, (low) indices, start at max z. Spiral is around Z axis.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;goldenAngleThree&lt;/span&gt; =  &lt;span style=&#34;color:#91d7e3&#34;&gt;Double&lt;/span&gt;.pi &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;*&lt;/span&gt; (&lt;span style=&#34;color:#f5a97f&#34;&gt;1&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;+&lt;/span&gt; (&lt;span style=&#34;color:#f5a97f&#34;&gt;5.0&lt;/span&gt;).squareRoot())
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;generatePoints_SOV2&lt;/span&gt;(&lt;span style=&#34;color:#91d7e3&#34;&gt;count&lt;/span&gt;:&lt;span style=&#34;color:#91d7e3&#34;&gt;Int&lt;/span&gt;, radius:&lt;span style=&#34;color:#91d7e3&#34;&gt;Double&lt;/span&gt;) -&amp;gt; [Vector] {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;points&lt;/span&gt;:[Vector] = []
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//original code uses numpy&amp;#39;s &amp;#34;arrange&amp;#34; (evenly spaced values&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//within a given interval) to create indices.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;for&lt;/span&gt; i &lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;0.&lt;/span&gt;.&amp;lt;&lt;span style=&#34;color:#91d7e3&#34;&gt;count&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//offset effects packing. See references in blog post.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//could also fuzz the value here to blur lines since not using arrange.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;shiftedIndex&lt;/span&gt; = &lt;span style=&#34;color:#91d7e3&#34;&gt;Double&lt;/span&gt;(i)&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;+&lt;/span&gt;&lt;span style=&#34;color:#f5a97f&#34;&gt;0.5&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//comparing to generatePoints_SOV1, functionally very similar&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//i.e. &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//    - get a value based on a percentage into the count &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//    - map it to a value between -1 and 1, &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//    - treat that as either the sin or cos value depending&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//      on which axis should be the spindle&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//In _SOV1 the Y is the spindle, here it will be the Z&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;polar&lt;/span&gt;:&lt;span style=&#34;color:#91d7e3&#34;&gt;Double&lt;/span&gt; = acos(&lt;span style=&#34;color:#f5a97f&#34;&gt;1&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;-&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;2&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;*&lt;/span&gt;shiftedIndex&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;/&lt;/span&gt;&lt;span style=&#34;color:#91d7e3&#34;&gt;Double&lt;/span&gt;(&lt;span style=&#34;color:#91d7e3&#34;&gt;count&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;azimuthal&lt;/span&gt;:&lt;span style=&#34;color:#91d7e3&#34;&gt;Double&lt;/span&gt; = goldenAngleThree &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;*&lt;/span&gt; shiftedIndex
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//As original, z-axis winding&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            points.append(Vector(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                x: cos(azimuthal) &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;*&lt;/span&gt; sin(polar),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                y: sin(azimuthal) &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;*&lt;/span&gt; sin(polar),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                z: cos(polar)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            ).scaled(by: radius))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//If would prefer y-axis instead.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//            points.append(Vector(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//                x: cos(azimuthal) * sin(polar),&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//                y: cos(polar),&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//                z: sin(azimuthal) * sin(polar)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//            ).scaled(by: radius))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; points
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;a href=&#34;spiralv2_20230725T204911.usda&#34;&gt;spiralv2 usda file&lt;/a&gt;&lt;/p&gt;
&lt;x3d width=&#39;500px&#39; height=&#39;400px&#39;&gt; 
&lt;scene&gt;
&lt;viewpoint position=&#34;0 0 50&#34;&gt;&lt;/viewpoint&gt;
&lt;inline url=&#34;spiralv2_20230725T204911.x3d&#34;&gt;&lt;/inline&gt; 
&lt;/scene&gt; 
&lt;/x3d&gt; 
&lt;h3 id=&#34;full-code&#34;&gt;Full code&lt;/h3&gt;
&lt;p&gt;&lt;a href=&#34;SpiralShell.swift&#34;&gt;SpiralShell.swift&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Note that my Vector type also newly has a &amp;ldquo;scaled(by)&amp;rdquo; value that multiplies each component of the vector. I&amp;rsquo;m not worrying about using &lt;a href=&#34;https://developer.apple.com/accelerate/&#34;&gt;&lt;code&gt;Accelerate&lt;/code&gt;&lt;/a&gt; or &lt;a href=&#34;https://developer.apple.com/documentation/swift/simd-vector-types&#34;&gt;&lt;code&gt;simd&lt;/code&gt;&lt;/a&gt; values at the moment to make this code faster because I&amp;rsquo;m just saving it to disk. The loaders and renderers need to have speed. This step not so much yet. TBD if I&amp;rsquo;ll pull in the PSVector type from (&lt;a href=&#34;https://github.com/carlynorama/ParticleSystem/blob/main/Sources/ParticleSystem/PSVector.swift&#34;&gt;Particle System&lt;/a&gt;)&lt;/p&gt;
&lt;h2 id=&#34;things-to-explore&#34;&gt;Things to Explore&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;QuickLook seems to have a limit of 199 for the number of root prims it will draw. Time for &lt;code&gt;over&lt;/code&gt;? Assemblages? Just a &lt;code&gt;Scene&lt;/code&gt;?&lt;/li&gt;
&lt;li&gt;How would I change the background color?&lt;/li&gt;
&lt;li&gt;What went wrong with the color in the ring X3D file?&lt;/li&gt;
&lt;li&gt;Note that I added &lt;code&gt;&amp;lt;viewpoint position=&amp;quot;0 0 50&amp;quot;&amp;gt;&amp;lt;/viewpoint&amp;gt;&lt;/code&gt; to the x3d embeds. How would I do that via my own code.&lt;/li&gt;
&lt;li&gt;Lat-Long layout&lt;/li&gt;
&lt;li&gt;Does Usd have such a thing as a &amp;ldquo;stroke&amp;rdquo; or &amp;ldquo;line&amp;rdquo;?&lt;/li&gt;
&lt;li&gt;Really miss having a loop.&lt;/li&gt;
&lt;li&gt;Different functions use different values for the &amp;ldquo;golden angle&amp;rdquo;. TODO: test actual speed difference? If it&amp;rsquo;s stored as a static who cares?
&lt;ul&gt;
&lt;li&gt;Double.pi * (3-(5.0).squareRoot()) // 2.399963229728653&lt;/li&gt;
&lt;li&gt;Double.pi * ((5.0).squareRoot() - 1.0) // 3.883222077450933&lt;/li&gt;
&lt;li&gt;Double.pi * (1 + (5.0).squareRoot()) //10.166407384630519
&lt;ul&gt;
&lt;li&gt;Wraps around to goldenAngleCompliment (582.5°-360°=222.5°)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;references&#34;&gt;References&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&#34;https://extremelearning.com.au/how-to-evenly-distribute-points-on-a-sphere-more-effectively-than-the-canonical-fibonacci-lattice/#more-3069&#34;&gt;https://extremelearning.com.au/how-to-evenly-distribute-points-on-a-sphere-more-effectively-than-the-canonical-fibonacci-lattice/#more-3069&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&#34;https://mathworld.wolfram.com/Sphere.html&#34;&gt;https://mathworld.wolfram.com/Sphere.html&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&#34;https://mathworld.wolfram.com/SphericalCode.html&#34;&gt;https://mathworld.wolfram.com/SphericalCode.html&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&#34;https://en.wikipedia.org/wiki/Spherical_coordinate_system&#34;&gt;https://en.wikipedia.org/wiki/Spherical_coordinate_system&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&#34;https://en.wikipedia.org/wiki/Spherical_geometry&#34;&gt;https://en.wikipedia.org/wiki/Spherical_geometry&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&#34;https://stackoverflow.com/questions/9600801/evenly-distributing-n-points-on-a-sphere&#34;&gt;https://stackoverflow.com/questions/9600801/evenly-distributing-n-points-on-a-sphere&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&#34;https://stackoverflow.com/questions/5408276/sampling-uniformly-distributed-random-points-inside-a-spherical-volume&#34;&gt;https://stackoverflow.com/questions/5408276/sampling-uniformly-distributed-random-points-inside-a-spherical-volume&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&#34;https://math.stackexchange.com/questions/1585975/how-to-generate-random-points-on-a-sphere&#34;&gt;https://math.stackexchange.com/questions/1585975/how-to-generate-random-points-on-a-sphere&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&#34;https://arxiv.org/pdf/0912.4540.pdf&#34;&gt;https://arxiv.org/pdf/0912.4540.pdf&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&#34;https://www.semanticscholar.org/paper/Fast-Surface-Particle-Repulsion-Heckbert/97a67e367e39762baf631f519c00fbfd1d5c009a?p2df&#34;&gt;https://www.semanticscholar.org/paper/Fast-Surface-Particle-Repulsion-Heckbert/97a67e367e39762baf631f519c00fbfd1d5c009a?p2df&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&#34;https://agupubs.onlinelibrary.wiley.com/doi/pdf/10.1029/2007GC001581&#34;&gt;https://agupubs.onlinelibrary.wiley.com/doi/pdf/10.1029/2007GC001581&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&#34;https://scholar.rose-hulman.edu/cgi/viewcontent.cgi?article=1387&amp;amp;context=rhumj&#34;&gt;https://scholar.rose-hulman.edu/cgi/viewcontent.cgi?article=1387&amp;amp;context=rhumj&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&#34;https://bendwavy.org/pack/pack.htm&#34;&gt;https://bendwavy.org/pack/pack.htm&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&#34;https://openprocessing.org/sketch/41142&#34;&gt;https://openprocessing.org/sketch/41142&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
</description>
    </item>
    
    
    
    <item>
      <title>Hello USD - Part 17: I&#39;ll build OpenUSD on my VM, how long could it take?</title>
      <link>https://whynotestflight.com/excuses/hello-usd-part-17-ill-build-openusd-on-my-vm-how-long-could-it-take/</link>
      <pubDate>Tue, 25 Jul 2023 00:00:00 +0000</pubDate>
      
      <guid>https://whynotestflight.com/excuses/hello-usd-part-17-ill-build-openusd-on-my-vm-how-long-could-it-take/</guid>
      <description>&lt;p&gt;I don&amp;rsquo;t want a GitHub Action to be the only way I find a problem with my code on Linux. If a test fails or the code won&amp;rsquo;t build I want to fix it in an environment with a faster feedback loop.  I already have an Ubuntu VM already setup for Swift development and it&amp;rsquo;s time to install OpenUSD on it.&lt;/p&gt;
&lt;h2 id=&#34;howd-this-get-to-be-a-whole-post-all-to-itself&#34;&gt;How&amp;rsquo;d this get to be a whole post all to itself??&lt;/h2&gt;
&lt;p&gt;This ended up taking ALL DAY, since SOMEONE decided to do this on a VM with only one &lt;a href=&#34;https://www.virtualbox.org/manual/ch03.html#settings-processor&#34;&gt;processor allocated&lt;/a&gt; to it. Also, I had only ~80 MB to spare on my Virtual Machine when it was done! Whew. I&amp;rsquo;m using up about 3 more gigs of space now.&lt;/p&gt;
&lt;p&gt;The number of cores matters because the &lt;a href=&#34;https://github.com/PixarAnimationStudios/OpenUSD/blob/release/build_scripts/build_usd.py&#34;&gt;python_build.py&lt;/a&gt; script actually does something pretty clever. They&amp;rsquo;ve designed it to run on multiple cores.  &lt;a href=&#34;https://www.gnu.org/software/make/manual/html_node/Options-Summary.html&#34;&gt;&lt;code&gt;make -j&lt;/code&gt;&lt;/a&gt; appears on lines 973, 982, 1033 with variables for the input, so somewhere else they&amp;rsquo;ve looked up the number of cores available.  The -j option sets the number of subcommands allowed.&lt;/p&gt;
&lt;p&gt;My build took so long because I gave this GIANT task, designed to work with multiple subprocesses, one measly wee little core. When installing OpenUSD a non VM, run the &lt;a href=&#34;https://www.computerhope.com/unix/top.htm&#34;&gt;&lt;code&gt;top&lt;/code&gt;&lt;/a&gt; command to see it throw itself a party.&lt;/p&gt;
&lt;p&gt;To see how many processors a machine has available, run &lt;code&gt;getconf _NPROCESSORS_ONLN&lt;/code&gt; (&lt;a href=&#34;https://stackoverflow.com/questions/6481005/how-to-obtain-the-number-of-cpus-cores-in-linux-from-the-command-line&#34;&gt;other ways&lt;/a&gt;)&lt;/p&gt;
&lt;p&gt;ProTip: &lt;a href=&#34;https://www.youtube.com/watch?v=WEa8AHVAffE&#34;&gt;Update the settings&lt;/a&gt; next time!&lt;/p&gt;
&lt;h2 id=&#34;what-was-on-it-before-i-started&#34;&gt;What was on it before I started&lt;/h2&gt;
&lt;p&gt;Previously on the VM as documented on &lt;a href=&#34;https://github.com/carlynorama/SwiftLIBPNG&#34;&gt;SwiftLIBPNG&lt;/a&gt;&amp;rsquo;s repo&lt;/p&gt;
&lt;p&gt;A VirtualBox machine running Ubuntu 22.04.2&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-zsh&#34; data-lang=&#34;zsh&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;sudo apt update
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;sudo apt upgrade
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;sudo apt install clang libicu-dev build-essential pkg-config
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;apt install git gh
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;apt install libpng-dev
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;mkdir ~/swift
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#91d7e3&#34;&gt;cd&lt;/span&gt; ~/swift
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# go to https://www.swift.org/download/#releases for current links&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;wget https://download.swift.org/swift-5.8-release/ubuntu2004/swift-5.8-RELEASE/swift-5.8-RELEASE-ubuntu20.04.tar.gz
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;tar xzf swift-5.8-RELEASE-ubuntu20.04.tar.gz &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#add v (xzvf) to see all files&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;mv swift-5.8-RELEASE-ubuntu22.04 5.8
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# swift.org recommended choice: add a simlink to `swift` command to `/usr/bin/` &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# instead of adding version folder to $PATH. &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;sudo ln -s ~/swift/5.8/usr/bin/swift /usr/bin/swift 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;swift --version
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;building-openusd&#34;&gt;Building OpenUSD&lt;/h2&gt;
&lt;p&gt;Steps make a working &lt;code&gt;usdview&lt;/code&gt; included build of OpenUSD&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-zsh&#34; data-lang=&#34;zsh&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;sudo apt install cmake &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# &amp;lt;==== Ended up being a mistake.  &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;python --version &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# 3.10.6, perfect&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;sudo apt install python3-pip
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;pip3 install PyOpenGL numpy Pyside6
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#As per warning&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#91d7e3&#34;&gt;export&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;PATH&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;$PATH&lt;/span&gt;:/home/ubuntu_admin/.local/bin;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;sudo apt-get install -y libgl1-mesa-dev libglu1-mesa-dev libxt-dev
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#91d7e3&#34;&gt;cd&lt;/span&gt; ~/Documents/GitHub
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;git clone https://github.com/PixarAnimationStudios/OpenUSD.git
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;python3 OpenUSD/build_scripts/build_usd.py ~/opb/OpenUSD_2023JUL24_default
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;No Joy.&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;ERROR: CMake version 3.24 or later required to build USD, but version found was 3.22.1
&lt;/code&gt;&lt;/pre&gt;&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://cmake.org/install/&#34;&gt;https://cmake.org/install/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://www.electronicjunkies.net/index.php/2021/04/13/install-any-version-of-cmake-on-ubuntu/&#34;&gt;https://www.electronicjunkies.net/index.php/2021/04/13/install-any-version-of-cmake-on-ubuntu/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://graspingtech.com/upgrade-cmake/&#34;&gt;https://graspingtech.com/upgrade-cmake/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-zsh&#34; data-lang=&#34;zsh&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# Remove previous cmake versions&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;sudo apt remove cmake
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;sudo apt purge --auto-remove cmake
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#91d7e3&#34;&gt;hash&lt;/span&gt; -r &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#console refresh&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;sudo apt-get install build-essential libssl-dev libssl-doc
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;wget https://github.com/Kitware/CMake/releases/download/v3.27.0/cmake-3.27.0.tar.gz
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;tar xf cmake-3.27.0.tar.gz
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#91d7e3&#34;&gt;cd&lt;/span&gt; cmake-3.27.0
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;./bootstrap
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;make 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;sudo make install
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#91d7e3&#34;&gt;hash&lt;/span&gt; -r
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;cmake --version
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Afterwards &lt;code&gt;python3 OpenUSD/build_scripts/build_usd.py ~/opb/OpenUSD_2023JUL24_default&lt;/code&gt; worked just fine.  Took forever. Had to delete a bunch of stuff on the VM so it would fit, but worked just fine.&lt;/p&gt;
&lt;h2 id=&#34;it-works&#34;&gt;It works!&lt;/h2&gt;
&lt;p&gt;I switched the setup in &lt;a href=&#34;https://github.com/carlynorama/USDTestingCLI/blob/main/Sources/USDTestingCLI/USDTestingCLI.swift&#34;&gt;USDTestingCLI.swift&lt;/a&gt;&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;MARK:&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt; --------------------- YOUR SETUP GOES HERE ------------------------&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;USDBuild&lt;/span&gt; = &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;/home/USERNAME/opb/OpenUSD_2023JUL24_default&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;pythonEnv&lt;/span&gt;:USDServiceProvider.PythonEnvironment = .systemDefault
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And it works!&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;error_found_linux.png&#34; alt=&#34;Screenshot of Ubuntu desktop with VSCode open to USDTestingCLI with the same output in the console as yesterday&amp;rsquo;s post had from the MacOS build.&#34;&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;usdview&lt;/code&gt;, too!&lt;/p&gt;
</description>
    </item>
    
    
    
    <item>
      <title>Hello USD - Part 16: Swift just sipping OpenUSD through... a pipe!</title>
      <link>https://whynotestflight.com/excuses/hello-usd-part-16-swift-just-sipping-openusd-through...-a-pipe/</link>
      <pubDate>Sun, 23 Jul 2023 00:00:00 +0000</pubDate>
      
      <guid>https://whynotestflight.com/excuses/hello-usd-part-16-swift-just-sipping-openusd-through...-a-pipe/</guid>
      <description>&lt;p&gt;I&amp;rsquo;ve mostly been working with OpenUSD via the command line, so I decided to take initial pass at interfacing with the OpenUSD library in Swift trough a &lt;a href=&#34;https://whynotestflight.com/excuses/getting-scripty/&#34;&gt;Swift launched shell&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I don&amp;rsquo;t need much. I&amp;rsquo;d like to:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A) &lt;a href=&#34;https://whynotestflight.com/excuses/hello-usd-part-7-where-my-error-messages-at/&#34;&gt;verify the file is valid&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;B) &lt;a href=&#34;https://whynotestflight.com/excuses/hello-usd-part-7-where-my-error-messages-at/&#34;&gt;compress them into crate files&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Related post: &lt;a href=&#34;https://whynotestflight.com/excuses/hello-usd-part-7-where-my-error-messages-at/&#34;&gt;Part 7: Where my error messages at????&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;m going to write the library package and a cli executable package separately a lá the &lt;a href=&#34;https://github.com/carlynorama/SwiftLIBPNG&#34;&gt;SwiftPNG&lt;/a&gt; and &lt;a href=&#34;https://github.com/carlynorama/clipng&#34;&gt;clipng&lt;/a&gt; pair to keep the cli code far away from the package I&amp;rsquo;ll eventually bring into &lt;a href=&#34;https://github.com/carlynorama/SketchPad&#34;&gt;SketchPad&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;New Repos: &lt;a href=&#34;https://github.com/carlynorama/USDTestingCLI&#34;&gt;USDTestingCLI&lt;/a&gt; | &lt;a href=&#34;https://github.com/carlynorama/USDServiceProvider&#34;&gt;USDServiceProvider&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The first chunk of the post covers setting up that CLI/Package pair and adding a shell call (&lt;code&gt;Process()&lt;/code&gt;). The OpenUSD part starts at &amp;ldquo;&lt;a href=&#34;#usdcat&#34;&gt;Really getting started: usdcat&lt;/a&gt;&amp;rdquo;&lt;/p&gt;
&lt;p&gt;End of Post Tagged Commits:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/carlynorama/USDTestingCLI/releases/tag/v0.0.0_proof_of_concept&#34;&gt;https://github.com/carlynorama/USDTestingCLI/releases/tag/v0.0.0_proof_of_concept&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/carlynorama/USDServiceProvider/releases/tag/v0.0.0_proof_of_concept&#34;&gt;https://github.com/carlynorama/USDServiceProvider/releases/tag/v0.0.0_proof_of_concept&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;make-the-project-scaffolding&#34;&gt;Make the project scaffolding&lt;/h2&gt;
&lt;h3 id=&#34;step-1-executable-package-test&#34;&gt;Step 1: Executable Package Test&lt;/h3&gt;
&lt;p&gt;I had XCode open so I didn&amp;rsquo;t &lt;a href=&#34;https://whynotestflight.com/excuses/hello-usd-part-8-multiball-moves-to-a-package/&#34;&gt;use the command line&lt;/a&gt;, I just &lt;code&gt;File &amp;gt; New &amp;gt; Package&lt;/code&gt;&amp;rsquo;d from the menu to create &lt;code&gt;USDTestingCLI&lt;/code&gt; and made the following changes&lt;/p&gt;
&lt;h4 id=&#34;update-usdtestingcliswift&#34;&gt;Update USDTestingCLI.swift&lt;/h4&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;@main
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;USDTestingCLI&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;main&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Hello world!&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h4 id=&#34;update-packageswift&#34;&gt;Update Package.swift&lt;/h4&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// swift-tools-version: 5.8&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// The swift-tools-version declares the minimum version of Swift required to build this package.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;PackageDescription&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;package&lt;/span&gt; = Package(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    name: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;USDTestingCLI&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    products: [
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        .executable(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            name: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;myusdtests&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            targets: [&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;USDTestingCLI&amp;#34;&lt;/span&gt;]),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    ],
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    dependencies: [ ],
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    targets: [
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        .executableTarget(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            name: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;USDTestingCLI&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            dependencies: []),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;         &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//None yet.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//        .testTarget(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//            name: &amp;#34;USDTestingCLITests&amp;#34;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//            dependencies: [&amp;#34;USDTestingCLI&amp;#34;]),&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    ]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Hit the &lt;code&gt;Run&lt;/code&gt; button (cmd-R) and &amp;ldquo;Hello world!&amp;rdquo; showed up in the console. Done.&lt;/p&gt;
&lt;h3 id=&#34;step-2-make-library-package&#34;&gt;Step 2: Make Library Package&lt;/h3&gt;
&lt;p&gt;Again just made another default package from &lt;code&gt;File &amp;gt; New &amp;gt; Package&lt;/code&gt;. This time making no changes, so the main file in Sources stays like:&lt;/p&gt;
&lt;h4 id=&#34;usdserviceproviderswift&#34;&gt;USDServiceProvider.swift&lt;/h4&gt;
&lt;p&gt;No Changes.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;USDServiceProvider&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;private&lt;/span&gt;(&lt;span style=&#34;color:#c6a0f6&#34;&gt;set&lt;/span&gt;) &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;text&lt;/span&gt; = &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Hello, World!&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;init&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;step-3-link-the-two&#34;&gt;Step 3: Link the two&lt;/h3&gt;
&lt;h4 id=&#34;usdtestingcli---usdtestingcliswift&#34;&gt;USDTestingCLI - USDTestingCLI.swift&lt;/h4&gt;
&lt;p&gt;Update the main file in the CLI Package to:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;Foundation&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;ArgumentParser&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;USDServiceProvider&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;@main
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;USDTestingCLI&lt;/span&gt;:ParsableCommand {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;configuration&lt;/span&gt; = CommandConfiguration(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        abstract: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;A Swift command-line tool to create 3D files from simple instructions&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        version: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;0.0.1&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        subcommands: [
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            test.&lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        ],
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        defaultSubcommand: test.&lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;init&lt;/span&gt;() {}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;test&lt;/span&gt;:ParsableCommand {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;run&lt;/span&gt;() &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(USDServiceProvider().text)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h4 id=&#34;usdtestingcli---packageswift&#34;&gt;USDTestingCLI - Package.swift&lt;/h4&gt;
&lt;p&gt;Add a local dependency.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// swift-tools-version: 5.8&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// The swift-tools-version declares the minimum version of Swift required to build this package.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;PackageDescription&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;package&lt;/span&gt; = Package(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    name: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;USDTestingCLI&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    products: [
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// Products define the executables and libraries a package produces, and make them visible to other packages.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        .executable(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            name: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;myusdtests&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            targets: [&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;USDTestingCLI&amp;#34;&lt;/span&gt;]),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    ],
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    dependencies: [
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        .package(url: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;https://github.com/apple/swift-argument-parser.git&amp;#34;&lt;/span&gt;, from: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;1.2.2&amp;#34;&lt;/span&gt;),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        .package(path: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;../USDServiceProvider&amp;#34;&lt;/span&gt;),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    ],
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    targets: [
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        .executableTarget(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            name: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;USDTestingCLI&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            dependencies: [
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                .product(name: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;ArgumentParser&amp;#34;&lt;/span&gt;, package: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;swift-argument-parser&amp;#34;&lt;/span&gt;),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                .product(name: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;USDServiceProvider&amp;#34;&lt;/span&gt;, package: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;USDServiceProvider&amp;#34;&lt;/span&gt;),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            ]),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        .testTarget(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            name: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;USDTestingCLITests&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            dependencies: [&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;USDTestingCLI&amp;#34;&lt;/span&gt;]),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    ]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Again, running via XCode (cmd-R) should work to see &amp;ldquo;Hello, World!&amp;rdquo; in the console.&lt;/p&gt;
&lt;h3 id=&#34;step-4-add-shell-commands&#34;&gt;Step 4: Add shell commands&lt;/h3&gt;
&lt;h4 id=&#34;usdserviceprovider---usdserviceproviderswift&#34;&gt;USDServiceProvider - USDServiceProvider.swift&lt;/h4&gt;
&lt;p&gt;Next I&amp;rsquo;m going to pull from &lt;a href=&#34;https://github.com/carlynorama/swift-scripting/blob/main/run_a_shell_script.swift&#34;&gt;previous work&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Useful links for understanding this code:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://stackoverflow.com/questions/26971240/how-do-i-run-a-terminal-command-in-a-swift-script-e-g-xcodebuild&#34;&gt;https://stackoverflow.com/questions/26971240/how-do-i-run-a-terminal-command-in-a-swift-script-e-g-xcodebuild&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://rderik.com/blog/using-swift-for-scripting/&#34;&gt;https://rderik.com/blog/using-swift-for-scripting/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://developer.apple.com/documentation/foundation/process&#34;&gt;https://developer.apple.com/documentation/foundation/process&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://www.hackingwithswift.com/example-code/system/how-to-run-an-external-program-using-process&#34;&gt;https://www.hackingwithswift.com/example-code/system/how-to-run-an-external-program-using-process&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I added the following to the &lt;code&gt;USDServiceProvider&lt;/code&gt; struct:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;     &lt;span style=&#34;color:#ed8796&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;echo&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; input:&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;) -&amp;gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; input.&lt;span style=&#34;color:#91d7e3&#34;&gt;isEmpty&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;[crickets chirping]&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        } &lt;span style=&#34;color:#c6a0f6&#34;&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;message&lt;/span&gt; = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt;? shell(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;echo &lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;input&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; (message &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;!=&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;nil&lt;/span&gt;) ? message! : &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;nothing to say&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    @discardableResult &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// Add to suppress warnings when you don&amp;#39;t want/need a result&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;shell&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; command: &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;) &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; -&amp;gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;task&lt;/span&gt; = &lt;span style=&#34;color:#91d7e3&#34;&gt;Process&lt;/span&gt;()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;pipe&lt;/span&gt; = Pipe()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        task.standardOutput = pipe
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        task.standardError = pipe
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        task.arguments = [&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;-c&amp;#34;&lt;/span&gt;, command]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        task.standardInput = &lt;span style=&#34;color:#f5a97f&#34;&gt;nil&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        task.executableURL = URL(fileURLWithPath: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;/bin/bash&amp;#34;&lt;/span&gt;) &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//&amp;lt;-- what shell&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; task.run()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;data&lt;/span&gt; = pipe.fileHandleForReading.readDataToEndOfFile()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;output&lt;/span&gt; = &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;(data: data, encoding: .utf8)&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;!&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; output
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;whatsInMyBin&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;testPath&lt;/span&gt; = &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;/usr/bin&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;ls&lt;/span&gt; = &lt;span style=&#34;color:#91d7e3&#34;&gt;Process&lt;/span&gt;()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//https://manned.org/env.1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        ls.executableURL = URL(fileURLWithPath: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;/usr/bin/env&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        ls.arguments = [&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;ls&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;-al&amp;#34;&lt;/span&gt;, testPath]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;do&lt;/span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; ls.run()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        } &lt;span style=&#34;color:#c6a0f6&#34;&gt;catch&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(error)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And changed the CLI test struct to:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;test&lt;/span&gt;:ParsableCommand {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;run&lt;/span&gt;() &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(USDServiceProvider().whatsInMyBin())
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(USDServiceProvider().echo(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;can you hear me?&amp;#34;&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;In a shell program (because the output is long):&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;cd ~/Developer/GitHub/USDTestingCLI &amp;amp; swift run myusdtests
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;I get a very very very long list of commands I could potentially use in my program!&lt;/p&gt;
&lt;h2 id=&#34;usdcat&#34;&gt;Really getting started: usdcat &lt;/h2&gt;
&lt;p&gt;&lt;code&gt;usdcat&lt;/code&gt; is a freestanding binary with no python dependencies. &lt;code&gt;usdchecker&lt;/code&gt;, on the other hand, is a python script with a shebang on the top. While it is &amp;ldquo;clickable&amp;rdquo;, it is not contained. Getting &lt;code&gt;usdcat&lt;/code&gt; to run on a known valid &lt;code&gt;.usda&lt;/code&gt; file will be much easier to implement than &lt;code&gt;usdchecker&lt;/code&gt;. The goal:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;usdcat -o $OUTPUT_NAME --flatten $INPUT_ROOT_FILE&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Since I know the location of the OpenUSD build I want to use, just to see if it works, I can change &lt;code&gt;USDServiceProvider&lt;/code&gt; to:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;USDServiceProvider&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;private&lt;/span&gt;(&lt;span style=&#34;color:#c6a0f6&#34;&gt;set&lt;/span&gt;) &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;pathToBin&lt;/span&gt;:&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;init&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; pathToUSD:&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;? = &lt;span style=&#34;color:#f5a97f&#34;&gt;nil&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;       pathToBin = &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;/Users/USERNAME/opd/USD_nousdview_0722/bin&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;usdcatHelp&lt;/span&gt;() -&amp;gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;message&lt;/span&gt; = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt;? &lt;span style=&#34;color:#f5a97f&#34;&gt;Self&lt;/span&gt;.shell(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;pathToBin&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;/usdcat -h&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; (message &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;!=&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;nil&lt;/span&gt;) ? message! : &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;nothing to say&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//NOTE: Changed to static&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    @discardableResult &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// Add to suppress warnings when you don&amp;#39;t want/need a result&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;shell&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; command: &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;) &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; -&amp;gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;task&lt;/span&gt; = &lt;span style=&#34;color:#91d7e3&#34;&gt;Process&lt;/span&gt;()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;pipe&lt;/span&gt; = Pipe()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        task.standardOutput = pipe
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        task.standardError = pipe
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        task.arguments = [&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;-c&amp;#34;&lt;/span&gt;, command]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        task.standardInput = &lt;span style=&#34;color:#f5a97f&#34;&gt;nil&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        task.executableURL = URL(fileURLWithPath: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;/bin/bash&amp;#34;&lt;/span&gt;) &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//&amp;lt;-- what shell&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; task.run()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;data&lt;/span&gt; = pipe.fileHandleForReading.readDataToEndOfFile()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;output&lt;/span&gt; = &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;(data: data, encoding: .utf8)&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;!&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; output
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;I can call it!&lt;/p&gt;
&lt;p&gt;But can I use it?&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;makeUSDC&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;inputFile&lt;/span&gt; = &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;/Users/USERNAME/Developer/GitHub/USDTestingCLI/compress_me.usda&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;outputFile&lt;/span&gt; = &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;/Users/USERNAME/Developer/GitHub/USDTestingCLI/compressed.usdc&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(&lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt;? shell(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;pwd&amp;#34;&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;message&lt;/span&gt; = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt;? shell(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;pathToBin&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;/usdcat -o &lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;outputFile&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt; --flatten &lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;inputFile&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(message)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Success!!!&lt;/p&gt;
&lt;p&gt;Note the call to &lt;a href=&#34;https://en.wikipedia.org/wiki/Pwd&#34;&gt;&lt;code&gt;pwd&lt;/code&gt;&lt;/a&gt; there. When using the XCode Run / Cmd-R button the print out reads:&lt;/p&gt;
&lt;p&gt;Optional(&amp;quot;/Users/USERNAME/Library/Developer/Xcode/DerivedData/USDTestingCLI-dabxknpcmjbcpiexpxknncyhvmiy/Build/Products/Debug\n&amp;quot;)&lt;/p&gt;
&lt;p&gt;But &lt;code&gt;swift run myusdtests&lt;/code&gt; from a shell within the CLI&amp;rsquo;s directory prints out the more reasonable:&lt;/p&gt;
&lt;p&gt;Optional(&amp;quot;/Users/USERNAME/Developer/GitHub/USDTestingCLI\n&amp;quot;)&lt;/p&gt;
&lt;p&gt;Just something to keep in mind when setting the input and output file locations.  XCode runs a CLI in a quarantined area, like an App, not in the &lt;code&gt;pwd&lt;/code&gt; of the project. Using full paths made it easier to run this quick test.&lt;/p&gt;
&lt;h2 id=&#34;using-the-python-for-usdchecker&#34;&gt;Using The Python for &lt;code&gt;usdchecker&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;usdchecker&lt;/code&gt; does not work with the default flavor of python installed on MacOS (3.11), although that appears to be fixable (see aside).&lt;/p&gt;
&lt;p&gt;ASIDE: boost problem w/ 3.11 (&lt;a href=&#34;https://github.com/boostorg/python/pull/385)&#34;&gt;https://github.com/boostorg/python/pull/385)&lt;/a&gt;, according to comment in &lt;a href=&#34;https://github.com/PixarAnimationStudios/OpenUSD/blob/release/build_scripts/build_usd.py&#34;&gt;OpenUSD build script&lt;/a&gt; can set a different version of boost via a build arg? &lt;code&gt;--build-args boost,cxxflags= &lt;/code&gt;&lt;/p&gt;
&lt;p&gt;IF the caller&amp;rsquo;s python environment could be dependably be the same as the build&amp;rsquo;s python environment, simply adding the following to the shell function would be fine:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;environment&lt;/span&gt; =  ProcessInfo.processInfo.environment
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    environment[&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;PYTHONPATH&amp;#34;&lt;/span&gt;] = &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;pathToPython&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    task.environment = environment
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(task.environment ?? &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;I don&amp;rsquo;t want to have to remember to only ever call my script from the perfect environment. My code can remember that for me. I already have script I can work from documented in a &lt;a href=&#34;https://github.com/carlynorama/USDHelloWorld/blob/main/SETUP.md&#34;&gt;SETUP file&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;USDService provider gets a new extension&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;extension&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;USDServiceProvider&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;environmentWrap&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; newCommand:&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;, python:PythonEnvironment) -&amp;gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&amp;#34;&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;        &lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;python.setString&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;        export PATH=$PATH:&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;pathToBaseDir&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;/bin;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;        export PYTHONPATH=$PYTHONPATH:&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;pathToBaseDir&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;/lib/python
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;        &lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;newCommand&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;        &amp;#34;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;enum&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;PythonEnvironment&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;case&lt;/span&gt; defaultSystem
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;case&lt;/span&gt; pyenv(&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;case&lt;/span&gt; systemInstallMacOS(&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;case&lt;/span&gt; customPath(&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;setString&lt;/span&gt;:&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;switch&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;case&lt;/span&gt; .defaultSystem:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;case&lt;/span&gt; .pyenv(&lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;v&lt;/span&gt;):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; setPythonWithPyEnv(version: v)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;case&lt;/span&gt; .systemInstallMacOS(&lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;v&lt;/span&gt;):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; setPythonSystemMacOS(version: v)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;case&lt;/span&gt; .customPath(&lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;p&lt;/span&gt;):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; prependPath(customString: p)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;setPythonWithPyEnv&lt;/span&gt;(version:&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;) -&amp;gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&amp;#34;&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;            export PYENV_ROOT=&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;$&lt;/span&gt;HOME&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;/&lt;/span&gt;.pyenv&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;            command -v pyenv &amp;gt;/dev/null || export PATH=&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;$&lt;/span&gt;PYENV_ROOT&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;/&lt;/span&gt;bin:&lt;span style=&#34;color:#ed8796&#34;&gt;$&lt;/span&gt;PATH&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;            eval &amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;$&lt;/span&gt;(pyenv &lt;span style=&#34;color:#ed8796&#34;&gt;init&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;-&lt;/span&gt;)&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;            export PYENV_VERSION=&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;version&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;            &amp;#34;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;setPythonSystemMacOS&lt;/span&gt;(version:&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;) -&amp;gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&amp;#34;&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;            PATH=&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;/&lt;/span&gt;Library&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;/&lt;/span&gt;Frameworks&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;/&lt;/span&gt;Python.framework&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;/&lt;/span&gt;Versions&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;/&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;\&lt;/span&gt;(version)&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;/&lt;/span&gt;bin:&lt;span style=&#34;color:#ed8796&#34;&gt;$&lt;/span&gt;{PATH}&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;            export PATH
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;            &amp;#34;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;prependPath&lt;/span&gt;(customString:&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;) -&amp;gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&amp;#34;&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;            PATH=&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;\&lt;/span&gt;(customString):&lt;span style=&#34;color:#ed8796&#34;&gt;$&lt;/span&gt;{PATH}&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;            export PATH
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;            &amp;#34;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;A new initializer&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;init&lt;/span&gt;(pathToUSDBuild:&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;, pythonEnv:PythonEnvironment) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;.pathToBaseDir = pathToUSDBuild
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;.pythonEnv = pythonEnv
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;and an update to the shell command&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        task.standardError = pipe
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//BELOW: NEW WRAPPER FOR TASK ARG&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        task.arguments = [&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;-c&amp;#34;&lt;/span&gt;, environmentWrap(command, python: pythonEnv)]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        task.standardInput = &lt;span style=&#34;color:#f5a97f&#34;&gt;nil&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The CLI gets a new command&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;checkncrate&lt;/span&gt;:ParsableCommand {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        @Argument(help: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;The input file&amp;#34;&lt;/span&gt;) &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;inputFile&lt;/span&gt;: &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        @Argument(help: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;The output file&amp;#34;&lt;/span&gt;) &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;outputFile&lt;/span&gt;: &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;?
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;run&lt;/span&gt;() &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;TODO:&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt; fragile. if cli sticks around, improve.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;outputFilePath&lt;/span&gt; = outputFile ?? inputFile.replacingOccurrences(of: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;.usda&amp;#34;&lt;/span&gt;, with: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;.usdc&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;usdSP&lt;/span&gt; = USDServiceProvider(pathToUSDBuild: USDBuild, pythonEnv: .pyenv(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;3.10&amp;#34;&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;hello&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;result&lt;/span&gt; = usdSP.check(inputFile)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(result)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            usdSP.makeCrate(from: inputFile, outputFile: outputFilePath)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;cd ~/Developer/GitHub/USDTestingCLI &amp;amp; swift run myusdtests compress_me.usda
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;a href=&#34;compress_me.usda&#34;&gt;compress_me.usda&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;results in&amp;hellip;&lt;/p&gt;
&lt;p&gt;FAILURE!!! I mean SUCCESS!!! I mean getting info about a failure IS success!!&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;fail_is_success.png&#34; alt=&#34;Building for debugging&amp;hellip;
[5/5] Linking myusdtests
Build complete! (0.91s)
hello
Stage does not specify its linear scale in metersPerUnit. (fails &amp;lsquo;StageMetadataChecker&amp;rsquo;)
Stage has missing or invalid defaultPrim. (fails &amp;lsquo;StageMetadataChecker&amp;rsquo;)
Failed!&#34;&gt;&lt;/p&gt;
&lt;p&gt;WHEW!&lt;/p&gt;
&lt;p&gt;Still a bit of a way to go before USDServiceProvider actually provides the services I want for SketchPad, but a nice start.&lt;/p&gt;
&lt;h2 id=&#34;wait-wait-one-more-thing&#34;&gt;Wait Wait&amp;hellip; one more thing.&lt;/h2&gt;
&lt;p&gt;A OpenUSD build isn&amp;rsquo;t confirmed working until the hello-world script is run&amp;hellip;&lt;/p&gt;
&lt;h3 id=&#34;added-to-usdtestingcliswift&#34;&gt;Added to &lt;code&gt;USDTestingCLI.swift&lt;/code&gt;&lt;/h3&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;helloworld&lt;/span&gt;:ParsableCommand {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        @Argument(help: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;The output file&amp;#34;&lt;/span&gt;) &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;outputFile&lt;/span&gt;: &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;?
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;run&lt;/span&gt;() &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;TODO:&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt; also fragile. if cli sticks around, improve.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;outputFilePath&lt;/span&gt; = outputFile ?? &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;~/Documents/hello_world.usda&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;usdSP&lt;/span&gt; = USDServiceProvider(pathToUSDBuild: USDBuild, pythonEnv: pythonEnv)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            usdSP.saveHelloWorld(to: outputFilePath)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;added-to-usdserviceproviderswift&#34;&gt;Added to USDServiceProvider.swift&lt;/h3&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// Works from Terminal other shell program, not so much XCode b/c of pyenv&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// &lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;TODO:&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt; Try on computer with system python USD Build&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;saveHelloWorld&lt;/span&gt;(to outputLocation:&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;current&lt;/span&gt; = URL(string: &lt;span style=&#34;color:#f5a97f&#34;&gt;#file&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;dir&lt;/span&gt; = current!.deletingLastPathComponent()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;message&lt;/span&gt; = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt;? shell(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;python3 &lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;dir&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;/python_scripts/hello_world.py &lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;outputLocation&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;message:&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;message ?? &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;no message&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;new-sourcesusdserviceproviderpython_scriptshello_worldpy&#34;&gt;NEW: Sources/USDServiceProvider/python_scripts/hello_world.py&lt;/h3&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8bd5ca&#34;&gt;from&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;pxr&lt;/span&gt; &lt;span style=&#34;color:#8bd5ca&#34;&gt;import&lt;/span&gt; Usd, UsdGeom
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8bd5ca&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;sys&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;main&lt;/span&gt;(output):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    stage &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; Usd&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;.&lt;/span&gt;Stage&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;.&lt;/span&gt;CreateNew(output)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    xformPrim &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; UsdGeom&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;.&lt;/span&gt;Xform&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;.&lt;/span&gt;Define(stage, &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#39;/hello&amp;#39;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    spherePrim &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; UsdGeom&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;.&lt;/span&gt;Sphere&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;.&lt;/span&gt;Define(stage, &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#39;/hello/world&amp;#39;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    stage&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;.&lt;/span&gt;GetRootLayer()&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;.&lt;/span&gt;Save()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;__name__&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;==&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;__main__&amp;#34;&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    main(sys&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;.&lt;/span&gt;argv[&lt;span style=&#34;color:#f5a97f&#34;&gt;1&lt;/span&gt;])
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Hello Sphere!!&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;composite_text_and_vis.png&#34; alt=&#34;Composite of two screenshots: A text editor with basic hello world text, and a QuickView window with our friend the sphere, once again.&#34;&gt;&lt;/p&gt;
</description>
    </item>
    
    
    
    <item>
      <title>Hello USD - Part 15: Can a GitHub Action cache a OpenUSD Build?</title>
      <link>https://whynotestflight.com/excuses/hello-usd-part-15-can-a-github-action-cache-a-openusd-build/</link>
      <pubDate>Sat, 22 Jul 2023 00:00:00 +0000</pubDate>
      
      <guid>https://whynotestflight.com/excuses/hello-usd-part-15-can-a-github-action-cache-a-openusd-build/</guid>
      <description>&lt;p&gt;Continuing my validation scheme&amp;hellip;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;input checked=&#34;&#34; disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; Is my code making the &lt;code&gt;.usda&lt;/code&gt; files I think it should be?  (XCTests) &lt;a href=&#34;https://whynotestflight.com/excuses/hello-usd-part-13-test-test-test/&#34;&gt;view&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;input checked=&#34;&#34; disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; Does my code compile on Linux? &lt;a href=&#34;https://whynotestflight.com/excuses/hello-usd-part-14-now-to-get-github-to-run-the-tests/&#34;&gt;view&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;input checked=&#34;&#34; disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; GitHub Action&lt;/li&gt;
&lt;li&gt;&lt;input checked=&#34;&#34; disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; VM&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;[] Are my &lt;code&gt;.usda&lt;/code&gt; files correct according to &lt;code&gt;usdchecker&lt;/code&gt;?
&lt;ul&gt;
&lt;li&gt;[] can I automate checking via swift&lt;/li&gt;
&lt;li&gt;[] could I even test that code on Linux with a GA &amp;lt;== WE ARE HERE&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I&amp;rsquo;m skipping a step because I don&amp;rsquo;t want everything I&amp;rsquo;ve just learned about GitHub actions to dribble out my ear before I tackled an even harder problem with them.&lt;/p&gt;
&lt;p&gt;TL;DR: &lt;a href=&#34;https://github.com/carlynorama/GHActionsForOpenUSD/&#34;&gt;https://github.com/carlynorama/GHActionsForOpenUSD/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;cache_control_panel.png&#34; alt=&#34;Screenshot of a GitHub repo’s Action cache control panel with several caches including one for a python build.&#34;&gt;&lt;/p&gt;
&lt;h2 id=&#34;approach&#34;&gt;Approach&lt;/h2&gt;
&lt;p&gt;As it turns out the folks managing the fabulous resource &lt;a href=&#34;https://github.com/usd-wg/assets/&#34;&gt;usg-assets&lt;/a&gt; are thinking about &lt;a href=&#34;https://github.com/usd-wg/assets/pull/49&#34;&gt;usd validation on GitHub&lt;/a&gt; themselves.&lt;/p&gt;
&lt;p&gt;They have wisely chosen the path of linking their checker to the &lt;a href=&#34;https://pypi.org/project/usd-core/&#34;&gt;pipy usd-core&lt;/a&gt; python resource so they can avoid managing yet another build artifact.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-yml&#34; data-lang=&#34;yml&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    - &lt;span style=&#34;color:#c6a0f6&#34;&gt;name&lt;/span&gt;: Set up Python
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#c6a0f6&#34;&gt;uses&lt;/span&gt;: actions/setup-python@v4
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#c6a0f6&#34;&gt;with&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#c6a0f6&#34;&gt;python-version&lt;/span&gt;: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#39;3.7&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    - &lt;span style=&#34;color:#c6a0f6&#34;&gt;name&lt;/span&gt;: Install usd-core PyPI package
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#c6a0f6&#34;&gt;run&lt;/span&gt;: pip install usd-core --user
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;I am not that wise.&lt;/p&gt;
&lt;p&gt;I also have a different problem.&lt;/p&gt;
&lt;p&gt;My Swift code won&amp;rsquo;t be running python, so a python library won&amp;rsquo;t help me.&lt;/p&gt;
&lt;p&gt;I need a github runner with OpenUSD installed that can also run Swift 5.9 (eventually, fingers crossed). But I don&amp;rsquo;t want to run the 1hr+ build (on their hardware) every time. What a waste.&lt;/p&gt;
&lt;p&gt;I could follow the route of &lt;a href=&#34;https://github.com/pablode/guc&#34;&gt;guc&lt;/a&gt;, where the author builds his own binaries in a different repo and then goes and gets them when he needs them. Super valid.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;m pretty clear for myself that I want more repo-by-repo flexibility, so I looked into GitHub&amp;rsquo;s &lt;a href=&#34;https://github.com/marketplace/actions/cache&#34;&gt;caching action&lt;/a&gt; which, turns out, does exactly what I wanted it to do!&lt;/p&gt;
&lt;p&gt;Note: I picked a manual-deletion &lt;a href=&#34;https://github.com/actions/cache/blob/main/caching-strategies.md&#34;&gt;caching strategy&lt;/a&gt;. The key is tied to the runner, and not the hash of any other resource (e.g. &lt;code&gt;key: ${{ runner.os }}-${{ hashFiles(&#39;**/lockfiles&#39;) }}&lt;/code&gt;). Once my repo builds the cache, it won&amp;rsquo;t invalidate until I delete it by hand.&lt;/p&gt;
&lt;p&gt;After many many false starts (GitHub Actions being WAY fiddlier than the total control I&amp;rsquo;m used to having) I got what I needed. I split the Clone &amp;amp; Build step into it&amp;rsquo;s own separate composite action so I wouldn&amp;rsquo;t have to &lt;code&gt;if&lt;/code&gt; against the cache key every step of it.&lt;/p&gt;
&lt;h3 id=&#34;cached-no-python-openusd-build&#34;&gt;Cached No-Python OpenUSD Build&lt;/h3&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;└── .github
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    └── workflows
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    │   └── main.yml
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    └── actions
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        └── clone_and_build_no_python
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            └── action.yml
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-yml&#34; data-lang=&#34;yml&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;##&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## GitHub Actions File&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## https://github.com/carlynorama/GHActionsForOpenUSD/&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## Carlyn Maw 2023 Jul 21&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;##&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## .github/workflows/main.yml&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;name&lt;/span&gt;: Build Linux
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# When and on what to run&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;on&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#c6a0f6&#34;&gt;push&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;branches&lt;/span&gt;: [ &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;main&amp;#34;&lt;/span&gt; ]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#c6a0f6&#34;&gt;pull_request&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;branches&lt;/span&gt;: [ &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;main&amp;#34;&lt;/span&gt; ]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;jobs&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#c6a0f6&#34;&gt;build&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;name&lt;/span&gt;: Build Linux
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;runs-on&lt;/span&gt;: ubuntu-latest &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# Base machine&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;steps&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## Get the files from the repo. &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## _Necessary_ because I call an external action in the repo.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      - &lt;span style=&#34;color:#c6a0f6&#34;&gt;name&lt;/span&gt;: Checkout This Repo
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;uses&lt;/span&gt;: actions/checkout@v3
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## updating apt-get, just good hygiene.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      - &lt;span style=&#34;color:#c6a0f6&#34;&gt;name&lt;/span&gt;: Update apt-get 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;run&lt;/span&gt;: sudo apt-get update
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## ubuntu-latest didn&amp;#39;t have OpenGL &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      - &lt;span style=&#34;color:#c6a0f6&#34;&gt;name&lt;/span&gt;: Set up packages (Linux)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;run&lt;/span&gt;: |&lt;span style=&#34;color:#6e738d&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d&#34;&gt;          sudo apt-get install -y libgl1-mesa-dev libglu1-mesa-dev&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## if the cache exists, recover it.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      - &lt;span style=&#34;color:#c6a0f6&#34;&gt;name&lt;/span&gt;: Restore OpenUSD (Repo and Build)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;id&lt;/span&gt;: cache-openusdnp-restore
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;uses&lt;/span&gt;: actions/cache/restore@v3
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;with&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#c6a0f6&#34;&gt;path&lt;/span&gt;: | &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# This is what I&amp;#39;m caching&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            OpenUSD_REPO
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            OpenUSD_BUILD_NOPYTHON
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#c6a0f6&#34;&gt;key&lt;/span&gt;: ${{ runner.os }}-openusdnp
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## If don&amp;#39;t find the cache go clone and build.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      - &lt;span style=&#34;color:#c6a0f6&#34;&gt;name&lt;/span&gt;: Build Fresh No Python
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt;: steps.cache-openusdnp-restore.outputs.cache-hit != &amp;#39;true&amp;#39;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;uses&lt;/span&gt;: ./.github/actions/clone_and_build_no_python
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## If do find the cache tell the environment variables.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      - &lt;span style=&#34;color:#c6a0f6&#34;&gt;name&lt;/span&gt;: Use Cached Build
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt;: steps.cache-openusdnp-restore.outputs.cache-hit == &amp;#39;true&amp;#39;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;run&lt;/span&gt;: |&lt;span style=&#34;color:#6e738d&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d&#34;&gt;          echo &amp;#34;USD_REPO_DIR=$PWD/OpenUSD_REPO&amp;#34; &amp;gt;&amp;gt; $GITHUB_ENV
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d&#34;&gt;          echo &amp;#34;USD_BUILD_DIR=$PWD/OpenUSD_BUILD_NOPYTHON&amp;#34; &amp;gt;&amp;gt; $GITHUB_ENV&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## Used for trouble shooting&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      - &lt;span style=&#34;color:#c6a0f6&#34;&gt;name&lt;/span&gt;: Tell me about the Environnement
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;run&lt;/span&gt;: |&lt;span style=&#34;color:#6e738d&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d&#34;&gt;          echo &amp;#34;-----&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d&#34;&gt;          pwd  
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d&#34;&gt;          ls
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d&#34;&gt;          which python3
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d&#34;&gt;          python3 --version
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d&#34;&gt;          which python
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d&#34;&gt;          python --version
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d&#34;&gt;          echo $GITHUB_WORKSPACE
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d&#34;&gt;          echo $PATH
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d&#34;&gt;          echo $GITHUB_ENV
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d&#34;&gt;          echo .env
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d&#34;&gt;          echo &amp;#34;-----&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      - &lt;span style=&#34;color:#c6a0f6&#34;&gt;name&lt;/span&gt;: Save OpenUSD Cache (Repo &amp;amp; Build)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;id&lt;/span&gt;: cache-openusdnp-save
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;uses&lt;/span&gt;: actions/cache/save@v3
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;with&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#c6a0f6&#34;&gt;path&lt;/span&gt;: |&lt;span style=&#34;color:#6e738d&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d&#34;&gt;            OpenUSD_REPO
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d&#34;&gt;            OpenUSD_BUILD_NOPYTHON&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#c6a0f6&#34;&gt;key&lt;/span&gt;: ${{ steps.cache-openusdnp-restore.outputs.cache-primary-key }}   
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## Make sure it runs with the full path name&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      - &lt;span style=&#34;color:#c6a0f6&#34;&gt;name&lt;/span&gt;: Confirms Runs
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;run&lt;/span&gt;: |&lt;span style=&#34;color:#6e738d&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d&#34;&gt;            $USD_BUILD_DIR/bin/usdcat -h&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## Add to $GITHUB_PATH and $GITHUB_ENV/PYTHONPATH &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## Otherwise won&amp;#39;t persist between steps. &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## Note: I did not add USD&amp;#39;s location to the PATH of THIS step&amp;#39;s shell. &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## Just the ones going forward.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      - &lt;span style=&#34;color:#c6a0f6&#34;&gt;name&lt;/span&gt;: Add OpenUSD Build to PATH and PYTHONPATH
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;run&lt;/span&gt;: |&lt;span style=&#34;color:#6e738d&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d&#34;&gt;          export PYTHONPATH=$PYTHONPATH:$USD_BUILD_DIR/lib/python 
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d&#34;&gt;          echo &amp;#34;$USD_BUILD_DIR/bin&amp;#34; &amp;gt;&amp;gt; $GITHUB_PATH
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d&#34;&gt;          echo &amp;#34;PYTHONPATH=$PYTHONPATH&amp;#34; &amp;gt;&amp;gt; $GITHUB_ENV&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## Did PATH updates work.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      - &lt;span style=&#34;color:#c6a0f6&#34;&gt;name&lt;/span&gt;: Confirm in Path
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;run&lt;/span&gt;: |&lt;span style=&#34;color:#6e738d&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d&#34;&gt;          usdcat -h&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-yml&#34; data-lang=&#34;yml&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;##&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## GitHub Actions File&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## https://github.com/carlynorama/GHActionsForOpenUSD/&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## Carlyn Maw 2023 Jul 21&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;##&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## .github/actions/clone_and_build_no_python/action.yml&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;name&lt;/span&gt;: Build Fresh No Python
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;runs&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#c6a0f6&#34;&gt;using&lt;/span&gt;: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#39;composite&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#c6a0f6&#34;&gt;steps&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# Uses actions/checkout@v3 with a specified repo&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    - &lt;span style=&#34;color:#c6a0f6&#34;&gt;name&lt;/span&gt;: Clone Pixar USD
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#c6a0f6&#34;&gt;uses&lt;/span&gt;: actions/checkout@v3
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#c6a0f6&#34;&gt;with&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;repository&lt;/span&gt;: PixarAnimationStudios/OpenUSD
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;path&lt;/span&gt;: OpenUSD_REPO
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# Pass location of repo back out into calling script&amp;#39;s GITHUB_ENV&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# Not perfect practice. It&amp;#39;s a side effect rather than an output.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    - &lt;span style=&#34;color:#c6a0f6&#34;&gt;name&lt;/span&gt;: Add Repo Location to GITHUB_ENV
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#c6a0f6&#34;&gt;run&lt;/span&gt;: |&lt;span style=&#34;color:#6e738d&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d&#34;&gt;        echo &amp;#34;USD_REPO_DIR=$PWD/OpenUSD_REPO&amp;#34; &amp;gt;&amp;gt; $GITHUB_ENV&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#c6a0f6&#34;&gt;shell&lt;/span&gt;: bash
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# Build and add the location to calling script&amp;#39;s GITHUB_ENV&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    - &lt;span style=&#34;color:#c6a0f6&#34;&gt;name&lt;/span&gt;: Build USD (no python)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#c6a0f6&#34;&gt;run&lt;/span&gt;: |&lt;span style=&#34;color:#6e738d&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d&#34;&gt;        python $USD_REPO_DIR/build_scripts/build_usd.py --no-python OpenUSD_BUILD_NOPYTHON
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d&#34;&gt;        echo &amp;#34;USD_BUILD_DIR=$PWD/OpenUSD_BUILD_NOPYTHON&amp;#34; &amp;gt;&amp;gt; $GITHUB_ENV&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#c6a0f6&#34;&gt;shell&lt;/span&gt;: bash
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# Did the build work? In this code I check that twice, &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# both inside the subaction  and back out in the main. &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    - &lt;span style=&#34;color:#c6a0f6&#34;&gt;name&lt;/span&gt;: Confirms Runs
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#c6a0f6&#34;&gt;run&lt;/span&gt;: |&lt;span style=&#34;color:#6e738d&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d&#34;&gt;          $USD_BUILD_DIR/bin/usdcat -h&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#c6a0f6&#34;&gt;shell&lt;/span&gt;: bash
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;misc-lessons&#34;&gt;Misc Lessons&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;EVERY STEP IS ITS OWN SHELL SESSION EVERY STEP IS ITS OWN SHELL SESSION EVERY STEP IS ITS OWN SHELL SESSION. Use $&lt;a href=&#34;https://docs.github.com/en/actions/learn-github-actions/variables&#34;&gt;GITHUB_ENV&lt;/a&gt; (and TODO: &lt;a href=&#34;https://github.blog/changelog/2021-11-10-github-actions-input-types-for-manual-workflows/&#34;&gt;inputs&lt;/a&gt; and &lt;a href=&#34;https://docs.github.com/en/actions/using-jobs/defining-outputs-for-jobs&#34;&gt;outputs&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;One &lt;a href=&#34;https://docs.github.com/en/actions/creating-actions/creating-a-composite-action&#34;&gt;can use shell scripts&lt;/a&gt; with GHA&amp;rsquo;s. Do more of that.&lt;/li&gt;
&lt;li&gt;The error messages when an action fails can be misleading. For example, &amp;ldquo;Can&amp;rsquo;t find the file&amp;rdquo; doesn&amp;rsquo;t mean that it can&amp;rsquo;t actually find the file, it may be that the file is poorly formatted or the code lacks permission to use it.&lt;/li&gt;
&lt;li&gt;VSCode&amp;rsquo;s &lt;a href=&#34;https://marketplace.visualstudio.com/items?itemName=github.vscode-github-actions&#34;&gt;GitHub Action Extension&lt;/a&gt; provides invaluable help.&lt;/li&gt;
&lt;li&gt;When a GitHub provided action lets the programmer specify a path it&amp;rsquo;s a relative path under $GITHUB_WORKSPACE, which typically maps to the root folder of the checked out repo.  This appears to require a literal string, i.e. cannot take a variable. (Jul 2023)&lt;/li&gt;
&lt;li&gt;In a sub-action every shell based step needs to be told which shell to use.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;using-calling-sub-actions&#34;&gt;Using calling sub-actions&lt;/h3&gt;
&lt;p&gt;A little primer on how to call an action in an external file depending on its location in or out of the calling repo.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-yml&#34; data-lang=&#34;yml&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;on&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#c6a0f6&#34;&gt;push&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;branches&lt;/span&gt;: [ &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;main&amp;#34;&lt;/span&gt; ]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#c6a0f6&#34;&gt;pull_request&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;branches&lt;/span&gt;: [ &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;main&amp;#34;&lt;/span&gt; ]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;jobs&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#c6a0f6&#34;&gt;build&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;name&lt;/span&gt;: Build Linux
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;runs-on&lt;/span&gt;: ubuntu-latest
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;steps&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      - &lt;span style=&#34;color:#c6a0f6&#34;&gt;name&lt;/span&gt;: Checkout This Repo
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;uses&lt;/span&gt;: actions/checkout@v3
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      - &lt;span style=&#34;color:#c6a0f6&#34;&gt;name&lt;/span&gt;: An actions folder in same repo
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;uses&lt;/span&gt;: ./actions/hello_action
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      - &lt;span style=&#34;color:#c6a0f6&#34;&gt;name&lt;/span&gt;: In .github/actions in same repo
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;uses&lt;/span&gt;: ./.github/actions/hello_action
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      - &lt;span style=&#34;color:#c6a0f6&#34;&gt;name&lt;/span&gt;: External repo
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;uses&lt;/span&gt;: carlynorama/GHActionsForOpenUSD/actions/hello_action@main
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;building-with-python&#34;&gt;Building With Python&lt;/h2&gt;
&lt;p&gt;If one instead needs the default build, which includes usdview, python packages need to be installed. That&amp;rsquo;s not my focus, but I provide the following example. This example &lt;a href=&#34;https://docs.github.com/en/actions/using-workflows/caching-dependencies-to-speed-up-workflows&#34;&gt;cache&amp;rsquo;s pip&lt;/a&gt; but the time difference between cached and uncached python for this project seems to be &amp;lt; 1 second. Worth the learning, not worth the doing.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-yml&#34; data-lang=&#34;yml&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;##&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## GitHub Actions File&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## https://github.com/carlynorama/GHActionsForOpenUSD/&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;##&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## .github/workflows/cached_default_cachedPython.yml&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## Carlyn Maw 2023 Jul 21&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;##&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;name&lt;/span&gt;: Run on Default Flavor (Cached Python)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;on&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#c6a0f6&#34;&gt;push&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;branches&lt;/span&gt;: [ &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;default_build_test&amp;#34;&lt;/span&gt; ]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#c6a0f6&#34;&gt;pull_request&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;branches&lt;/span&gt;: [ &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;default_build_test&amp;#34;&lt;/span&gt; ]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;jobs&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#c6a0f6&#34;&gt;build&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;name&lt;/span&gt;: Try Default (Cached Python)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;runs-on&lt;/span&gt;: ubuntu-latest
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;steps&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      - &lt;span style=&#34;color:#c6a0f6&#34;&gt;name&lt;/span&gt;: Checkout This Repo
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;uses&lt;/span&gt;: actions/checkout@v3
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      - &lt;span style=&#34;color:#c6a0f6&#34;&gt;name&lt;/span&gt;: apt-get setup
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;uses&lt;/span&gt;: carlynorama/GHActionsForOpenUSD/actions/apt_get_update_install@main
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## Python setup script seems to have difficulty with foreign repo call&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## Note that this one refers to an action folder in the repo.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      - &lt;span style=&#34;color:#c6a0f6&#34;&gt;name&lt;/span&gt;: Setup Python
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;uses&lt;/span&gt;: actions/setup-python@v4
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;with&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# 3.10 is default&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#c6a0f6&#34;&gt;python-version&lt;/span&gt;: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#39;3.10&amp;#39;&lt;/span&gt;  
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#c6a0f6&#34;&gt;cache&lt;/span&gt;: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#39;pip&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# caching pip dependencies&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# Caching, by default, pins itself to changes in requirements.txt&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# I&amp;#39;m testing what overriding that means&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#c6a0f6&#34;&gt;cache-dependency-path&lt;/span&gt;: actions/python_cached_setup/requirements.txt
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      - &lt;span style=&#34;color:#c6a0f6&#34;&gt;name&lt;/span&gt;: Upgrade
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;shell&lt;/span&gt;: bash
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;run&lt;/span&gt;: |&lt;span style=&#34;color:#6e738d&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d&#34;&gt;          python -m pip install --upgrade pip&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      - &lt;span style=&#34;color:#c6a0f6&#34;&gt;name&lt;/span&gt;: Install
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;shell&lt;/span&gt;: bash
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;run&lt;/span&gt;: |&lt;span style=&#34;color:#6e738d&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d&#34;&gt;          pip install install -r actions/python_cached_setup/requirements.txt&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      - &lt;span style=&#34;color:#c6a0f6&#34;&gt;name&lt;/span&gt;: Restore OpenUSD (Repo and Build)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;id&lt;/span&gt;: cache-openusddf-restore
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;uses&lt;/span&gt;: actions/cache/restore@v3
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;with&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#c6a0f6&#34;&gt;path&lt;/span&gt;: |&lt;span style=&#34;color:#6e738d&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d&#34;&gt;            OpenUSD_REPO
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d&#34;&gt;            OpenUSD_BUILD_DEFAULT&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#c6a0f6&#34;&gt;key&lt;/span&gt;: ${{ runner.os }}-openusddf
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      - &lt;span style=&#34;color:#c6a0f6&#34;&gt;name&lt;/span&gt;: Build Fresh
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt;: steps.cache-openusddf-restore.outputs.cache-hit != &amp;#39;true&amp;#39;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;uses&lt;/span&gt;: carlynorama/GHActionsForOpenUSD/actions/clone_and_build_default@main
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      - &lt;span style=&#34;color:#c6a0f6&#34;&gt;name&lt;/span&gt;: Use Cached Build
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt;: steps.cache-openusddf-restore.outputs.cache-hit == &amp;#39;true&amp;#39;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;run&lt;/span&gt;: |&lt;span style=&#34;color:#6e738d&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d&#34;&gt;          echo &amp;#34;USD_REPO_DIR=$PWD/OpenUSD_REPO&amp;#34; &amp;gt;&amp;gt; $GITHUB_ENV
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d&#34;&gt;          echo &amp;#34;USD_BUILD_DIR=$PWD/OpenUSD_BUILD_DEFAULT&amp;#34; &amp;gt;&amp;gt; $GITHUB_ENV&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      - &lt;span style=&#34;color:#c6a0f6&#34;&gt;name&lt;/span&gt;: Save OpenUSD Cache (Repo &amp;amp; Build)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;id&lt;/span&gt;: cache-openusddf-save
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;uses&lt;/span&gt;: actions/cache/save@v3
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;with&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#c6a0f6&#34;&gt;path&lt;/span&gt;: |&lt;span style=&#34;color:#6e738d&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d&#34;&gt;            OpenUSD_REPO
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d&#34;&gt;            OpenUSD_BUILD_DEFAULT&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#c6a0f6&#34;&gt;key&lt;/span&gt;: ${{ steps.cache-openusddf-restore.outputs.cache-primary-key }}   
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      - &lt;span style=&#34;color:#c6a0f6&#34;&gt;name&lt;/span&gt;: Confirms Runs
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;run&lt;/span&gt;: |&lt;span style=&#34;color:#6e738d&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d&#34;&gt;            $USD_BUILD_DIR/bin/usdcat -h&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      - &lt;span style=&#34;color:#c6a0f6&#34;&gt;name&lt;/span&gt;: Add OpenUSD Build to PATH and PYTHONPATH
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;run&lt;/span&gt;: |&lt;span style=&#34;color:#6e738d&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d&#34;&gt;          export PYTHONPATH=$PYTHONPATH:$USD_BUILD_DIR/lib/python 
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d&#34;&gt;          echo &amp;#34;$USD_BUILD_DIR/bin&amp;#34; &amp;gt;&amp;gt; $GITHUB_PATH
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d&#34;&gt;          echo &amp;#34;PYTHONPATH=$PYTHONPATH&amp;#34; &amp;gt;&amp;gt; $GITHUB_ENV&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      - &lt;span style=&#34;color:#c6a0f6&#34;&gt;name&lt;/span&gt;: Confirm in Path
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;run&lt;/span&gt;: |&lt;span style=&#34;color:#6e738d&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d&#34;&gt;          usdcat -h&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;references&#34;&gt;References&lt;/h2&gt;
&lt;h3 id=&#34;github-docs&#34;&gt;GitHub Docs&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Python Setup and Caching - &lt;a href=&#34;https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-python&#34;&gt;https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-python&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Caching effects
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/actions/cache&#34;&gt;https://github.com/actions/cache&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/marketplace/actions/cache&#34;&gt;https://github.com/marketplace/actions/cache&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Updating the system path: &lt;a href=&#34;https://docs.github.com/en/actions/using-workflows/workflow-commands-for-github-actions#adding-a-system-path&#34;&gt;https://docs.github.com/en/actions/using-workflows/workflow-commands-for-github-actions#adding-a-system-path&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://docs.github.com/en/actions/using-workflows/caching-dependencies-to-speed-up-workflows&#34;&gt;https://docs.github.com/en/actions/using-workflows/caching-dependencies-to-speed-up-workflows&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://docs.github.com/en/actions/using-jobs/defining-outputs-for-jobs&#34;&gt;https://docs.github.com/en/actions/using-jobs/defining-outputs-for-jobs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.blog/changelog/2021-11-10-github-actions-input-types-for-manual-workflows/&#34;&gt;https://github.blog/changelog/2021-11-10-github-actions-input-types-for-manual-workflows/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://docs.github.com/en/actions/learn-github-actions/variables&#34;&gt;https://docs.github.com/en/actions/learn-github-actions/variables&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;runner-image-info&#34;&gt;Runner Image Info&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://docs.github.com/en/actions/using-github-hosted-runners/about-github-hosted-runners&#34;&gt;https://docs.github.com/en/actions/using-github-hosted-runners/about-github-hosted-runners&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/actions/runner-images/blob/main/images/linux/Ubuntu2204-Readme.md&#34;&gt;https://github.com/actions/runner-images/blob/main/images/linux/Ubuntu2204-Readme.md&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;example-actions-dockerfiles-workflows-stackoverflow-answers&#34;&gt;Example Actions, Dockerfiles, Workflows, StackOverflow answers&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/AnimalLogic/docker-usd&#34;&gt;https://github.com/AnimalLogic/docker-usd&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/pablode/USD/blob/v22.11-ci/.github/workflows/deploy-release.yml&#34;&gt;https://github.com/pablode/USD/blob/v22.11-ci/.github/workflows/deploy-release.yml&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/pablode/guc/tree/main/.github/workflows&#34;&gt;https://github.com/pablode/guc/tree/main/.github/workflows&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/usd-wg/assets/pull/49&#34;&gt;https://github.com/usd-wg/assets/pull/49&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/usd-wg/assets/pull/48&#34;&gt;https://github.com/usd-wg/assets/pull/48&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://stackoverflow.com/questions/59269850/caching-apt-packages-in-github-actions-workflow&#34;&gt;https://stackoverflow.com/questions/59269850/caching-apt-packages-in-github-actions-workflow&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;handy-snippet&#34;&gt;Handy Snippet&lt;/h2&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-sh&#34; data-lang=&#34;sh&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#91d7e3&#34;&gt;echo&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;-----&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#91d7e3&#34;&gt;pwd&lt;/span&gt;  
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          ls
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          which python3
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          python3 --version
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          which python
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          python --version
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#91d7e3&#34;&gt;echo&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;$GITHUB_WORKSPACE&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#91d7e3&#34;&gt;echo&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;$PATH&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#91d7e3&#34;&gt;echo&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;$GITHUB_PATH&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#91d7e3&#34;&gt;echo&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;$GITHUB_ENV&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#91d7e3&#34;&gt;echo&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;$PYTHONPATH&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#91d7e3&#34;&gt;echo&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;-----&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#f4dbd6&#34;&gt;$USD_BUILD_DIR&lt;/span&gt;/bin/usdcat -h
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          usdcat -h
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description>
    </item>
    
    
    
    <item>
      <title>Hello USD - Part 14: Now to get GitHub to run the tests</title>
      <link>https://whynotestflight.com/excuses/hello-usd-part-14-now-to-get-github-to-run-the-tests/</link>
      <pubDate>Thu, 20 Jul 2023 00:00:00 +0000</pubDate>
      
      <guid>https://whynotestflight.com/excuses/hello-usd-part-14-now-to-get-github-to-run-the-tests/</guid>
      <description>&lt;ul&gt;
&lt;li&gt;&lt;input checked=&#34;&#34; disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; Is my code making the &lt;code&gt;.usda&lt;/code&gt; files I think it should be?  (XCTests)&lt;/li&gt;
&lt;li&gt;[] Does my code compile on Linux?
&lt;ul&gt;
&lt;li&gt;[] GitHub Action &amp;lt;== WE ARE HERE&lt;/li&gt;
&lt;li&gt;[] VM &amp;lt;== AND HERE&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;[] Are my &lt;code&gt;.usda&lt;/code&gt; files correct according to &lt;code&gt;usdchecker&lt;/code&gt;?&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Most of the GitHub Action workflow files discussed can be found at:
&lt;a href=&#34;https://github.com/carlynorama/SketchPad/tree/main/.github/workflows&#34;&gt;https://github.com/carlynorama/SketchPad/tree/main/.github/workflows&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;(July 2023, Swift 5.8, Ubuntu 22.04, MacOS&amp;rsquo;s 12 and 13)&lt;/p&gt;
&lt;h2 id=&#34;for-linux&#34;&gt;For Linux&lt;/h2&gt;
&lt;p&gt;Since so much of the OpenUSD world seems to be focused on Linux work stations, I&amp;rsquo;d like SketchPad to run on them.  While I do have a actual Linux machines and VM&amp;rsquo;s to test on at home, a GitHub action will let me know faster.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://github.com/carlynorama/SketchPad/&#34;&gt;SketchPad&lt;/a&gt; doesn&amp;rsquo;t have a lot of bells or whistles so a fairly simple GitHub Action will work for it.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-yml&#34; data-lang=&#34;yml&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;name&lt;/span&gt;: Swift, Linux Latest (swift-actions)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;on&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#c6a0f6&#34;&gt;push&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;branches&lt;/span&gt;: [ &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;main&amp;#34;&lt;/span&gt; ]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#c6a0f6&#34;&gt;pull_request&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;branches&lt;/span&gt;: [ &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;main&amp;#34;&lt;/span&gt; ]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;jobs&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#c6a0f6&#34;&gt;build&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;runs-on&lt;/span&gt;: ubuntu-latest
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;steps&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## NOTE: better practice to point to a hash.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    - &lt;span style=&#34;color:#c6a0f6&#34;&gt;uses&lt;/span&gt;: swift-actions/setup-swift@v1 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#c6a0f6&#34;&gt;with&lt;/span&gt;: 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#c6a0f6&#34;&gt;swift-version&lt;/span&gt;: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;5.8&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    - &lt;span style=&#34;color:#c6a0f6&#34;&gt;uses&lt;/span&gt;: actions/checkout@v3
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    - &lt;span style=&#34;color:#c6a0f6&#34;&gt;name&lt;/span&gt;: Build
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#c6a0f6&#34;&gt;run&lt;/span&gt;: swift build -v
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    - &lt;span style=&#34;color:#c6a0f6&#34;&gt;name&lt;/span&gt;: Run tests
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#c6a0f6&#34;&gt;run&lt;/span&gt;: swift test -v
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The above example uses a 3rd party plugin called &lt;a href=&#34;https://github.com/marketplace/actions/setup-swift&#34;&gt;Setup Swift&lt;/a&gt; by &lt;a href=&#34;https://github.com/swift-actions&#34;&gt;Swift Actions&lt;/a&gt;, but there are many in the &lt;a href=&#34;https://github.com/marketplace?type=actions&amp;amp;query=swift+&#34;&gt;GitHub action marketplace&lt;/a&gt; that allow for configuration as needed.&lt;/p&gt;
&lt;p&gt;I wrote that action from a combo of a couple found &lt;a href=&#34;https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-swift&#34;&gt;in official GitHub documentaion&lt;/a&gt;, but I am explicitly NOT pointing at the hash or subversion. If the latest update breaks my build, I want to know.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;d forgotten that &lt;a href=&#34;https://github.com/carlynorama/SwiftLIBPNG/blob/main/.github/workflows/swift_linux.yml&#34;&gt;last time&lt;/a&gt; I used the &lt;a href=&#34;https://hub.docker.com/_/swift&#34;&gt;official swift docker container&lt;/a&gt;. That version also works.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://docs.github.com/en/actions/using-jobs/running-jobs-in-a-container&#34;&gt;How to use containers&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://docs.github.com/en/actions/creating-actions/creating-a-docker-container-action&#34;&gt;Docker actions&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-yml&#34; data-lang=&#34;yml&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;name&lt;/span&gt;: Swift, Latest Ubuntu, Container
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;on&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#c6a0f6&#34;&gt;push&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;branches&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      - &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#39;*&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#c6a0f6&#34;&gt;pull_request&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;branches&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      - main
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;jobs&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#c6a0f6&#34;&gt;build&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;name&lt;/span&gt;: Build Linux
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;runs-on&lt;/span&gt;: ubuntu-latest
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;container&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#c6a0f6&#34;&gt;image&lt;/span&gt;: swift:latest
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;steps&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      - &lt;span style=&#34;color:#c6a0f6&#34;&gt;name&lt;/span&gt;: Checkout
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;uses&lt;/span&gt;: actions/checkout@v3
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      - &lt;span style=&#34;color:#c6a0f6&#34;&gt;name&lt;/span&gt;: Build
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;run&lt;/span&gt;: |&lt;span style=&#34;color:#6e738d&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d&#34;&gt;           swift build -v&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      - &lt;span style=&#34;color:#c6a0f6&#34;&gt;name&lt;/span&gt;: Test
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;run&lt;/span&gt;: |&lt;span style=&#34;color:#6e738d&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d&#34;&gt;            swift test -v&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;for-macos&#34;&gt;For MacOS&lt;/h2&gt;
&lt;p&gt;It&amp;rsquo;s actually HARDER to get Swift 5.8 running on a MacOS runner.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;macos-latest&lt;/code&gt; has two problems.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Runs &lt;a href=&#34;https://github.blog/changelog/2022-10-03-github-actions-jobs-running-on-macos-latest-are-now-running-on-macos-12/&#34;&gt;macOS 12 officially&lt;/a&gt;. Interestingly I saw it both pass and fail my new  &lt;code&gt;if #available(macOS 13, *)&lt;/code&gt; RegexBuilder. &lt;a href=&#34;https://github.com/actions/runner-images/blob/main/images/macos/macos-12-Readme.md&#34;&gt;Build Details&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Uses Swift Tools version 5.7&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;redoing-regex&#34;&gt;Redoing Regex&lt;/h3&gt;
&lt;p&gt;Just to not have to worry about it I swapped out the fancy RegexBuilder code with the older style.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;headerMatch&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; toTest:&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;) -&amp;gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;Bool&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;pattern&lt;/span&gt; = #&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;^#usda 1\.0&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\n&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;[&lt;span style=&#34;color:#ed8796&#34;&gt;\&lt;/span&gt;s&lt;span style=&#34;color:#ed8796&#34;&gt;\&lt;/span&gt;S]&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;+&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;\&lt;/span&gt;n&lt;span style=&#34;color:#ed8796&#34;&gt;\&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;$&amp;#34;&lt;/span&gt;#
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;result&lt;/span&gt; = toTest.range(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            of: pattern,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            options: .regularExpression
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        )
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; (result &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;!=&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;nil&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h4 id=&#34;helpful-regex-links&#34;&gt;Helpful Regex Links:&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://paiv.github.io/swift-rxbgen/&#34;&gt;https://paiv.github.io/swift-rxbgen/&lt;/a&gt; -&amp;gt; RegexBuilder converter. Found it helpful to verify I was doing what I thought I was. It translated my new regex literal to the below.&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;regex&lt;/span&gt; = Regex {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          Anchor.startOfLine
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;#usda 1.0&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          Capture {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          OneOrMore {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            CharacterClass(.whitespace, .whitespace.inverted)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//I would choose could be CharacterClass.any, because .any matches newline, unlike `.`&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\n&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;)&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          Anchor.endOfLine &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//should be Anchor.endOfSubject?&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ul&gt;
&lt;li&gt;Shows older style of working with regex in Swift: &lt;a href=&#34;https://www.advancedswift.com/regular-expressions/&#34;&gt;https://www.advancedswift.com/regular-expressions/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Never not useful: &lt;a href=&#34;https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions/Cheatsheet&#34;&gt;https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions/Cheatsheet&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Using regex literals in Packages before using 5.9: &lt;a href=&#34;https://stackoverflow.com/questions/75573646/does-the-swift-package-manager-support-regex-literals&#34;&gt;https://stackoverflow.com/questions/75573646/does-the-swift-package-manager-support-regex-literals&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Using regex in scripts: &lt;a href=&#34;https://stackoverflow.com/questions/75615132/can-regex-literals-be-used-in-a-swift-script&#34;&gt;https://stackoverflow.com/questions/75615132/can-regex-literals-be-used-in-a-swift-script&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;working-github-action-a&#34;&gt;Working GitHub Action A&lt;/h3&gt;
&lt;p&gt;The following GitHub action runs consistently successfully for my code.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-yml&#34; data-lang=&#34;yml&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;name&lt;/span&gt;: Swift, MacOS, Swift 5.8
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;on&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#c6a0f6&#34;&gt;push&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;branches&lt;/span&gt;: [ &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;main&amp;#34;&lt;/span&gt; ]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#c6a0f6&#34;&gt;pull_request&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;branches&lt;/span&gt;: [ &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;main&amp;#34;&lt;/span&gt; ]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;jobs&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#c6a0f6&#34;&gt;build&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;runs-on&lt;/span&gt;: macos-latest
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;steps&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;##NOTE: better practice to point to hash.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    - &lt;span style=&#34;color:#c6a0f6&#34;&gt;uses&lt;/span&gt;: swift-actions/setup-swift@v1 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#c6a0f6&#34;&gt;with&lt;/span&gt;: 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#c6a0f6&#34;&gt;swift-version&lt;/span&gt;: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;5.8&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    - &lt;span style=&#34;color:#c6a0f6&#34;&gt;uses&lt;/span&gt;: actions/checkout@v3
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    - &lt;span style=&#34;color:#c6a0f6&#34;&gt;name&lt;/span&gt;: Build
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#c6a0f6&#34;&gt;run&lt;/span&gt;: swift build -v
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    - &lt;span style=&#34;color:#c6a0f6&#34;&gt;name&lt;/span&gt;: Run tests
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#c6a0f6&#34;&gt;run&lt;/span&gt;: swift test -v
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;working-github-action-b&#34;&gt;Working GitHub Action B&lt;/h3&gt;
&lt;p&gt;For the record, GitHub allows requests for &lt;a href=&#34;https://github.com/actions/runner-images&#34;&gt;specific version of macOS&lt;/a&gt;. MacOS 13 is currently in Beta. (&lt;code&gt;macos-13&lt;/code&gt; or &lt;code&gt;macos-13-xl&lt;/code&gt;). &lt;a href=&#34;https://github.com/actions/runner-images/blob/main/images/macos/macos-13-Readme.md&#34;&gt;Runner Build details&lt;/a&gt;&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-yml&#34; data-lang=&#34;yml&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;name&lt;/span&gt;: Swift, MacOS, Force 13
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;on&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#c6a0f6&#34;&gt;push&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;branches&lt;/span&gt;: [ $default-branch ]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#c6a0f6&#34;&gt;pull_request&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;branches&lt;/span&gt;: [ $default-branch ]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;jobs&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#c6a0f6&#34;&gt;build&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;runs-on&lt;/span&gt;: macos-13
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;steps&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    - &lt;span style=&#34;color:#c6a0f6&#34;&gt;uses&lt;/span&gt;: actions/checkout@v3
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    - &lt;span style=&#34;color:#c6a0f6&#34;&gt;name&lt;/span&gt;: Build
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#c6a0f6&#34;&gt;run&lt;/span&gt;: swift build -v
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    - &lt;span style=&#34;color:#c6a0f6&#34;&gt;name&lt;/span&gt;: Run tests
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#c6a0f6&#34;&gt;run&lt;/span&gt;: swift test -v
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;unused-matrix-action&#34;&gt;Unused Matrix Action&lt;/h2&gt;
&lt;p&gt;Helpful action that can check multiple OS&amp;rsquo;s and swift versions. Included for reference (updated from that GitHub link in the Linux section), but I personally prefer separate scripts so I can see at least SOME green check marks.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-yml&#34; data-lang=&#34;yml&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;name&lt;/span&gt;: Swift Matrix, v2
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;on&lt;/span&gt;: [push]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;jobs&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#c6a0f6&#34;&gt;build&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;name&lt;/span&gt;: Swift ${{ matrix.swift }} on ${{ matrix.os }}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;strategy&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#c6a0f6&#34;&gt;matrix&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;os&lt;/span&gt;: [ubuntu-latest, macos-latest]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;swift&lt;/span&gt;: [&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;5.8&amp;#34;&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;runs-on&lt;/span&gt;: ${{ matrix.os }}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;steps&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      - &lt;span style=&#34;color:#c6a0f6&#34;&gt;uses&lt;/span&gt;: swift-actions/setup-swift@v1
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;with&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#c6a0f6&#34;&gt;swift-version&lt;/span&gt;: ${{ matrix.swift }}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      - &lt;span style=&#34;color:#c6a0f6&#34;&gt;uses&lt;/span&gt;: actions/checkout@v3
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      - &lt;span style=&#34;color:#c6a0f6&#34;&gt;name&lt;/span&gt;: Build
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;run&lt;/span&gt;: swift build
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      - &lt;span style=&#34;color:#c6a0f6&#34;&gt;name&lt;/span&gt;: Run tests
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;run&lt;/span&gt;: swift test
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;confirming-on-the-vm&#34;&gt;Confirming on the VM&lt;/h2&gt;
&lt;p&gt;Opened up the VirtualBox instance &lt;a href=&#34;https://whynotestflight.com/excuses/now-i-need-linux-to-test-on./&#34;&gt;set up for testing Tipsy-Robot&lt;/a&gt;. I installed Swift by hand on that VM. Notes in the link. Next one I might try this tool: &lt;a href=&#34;https://github.com/stevapple/swiftbox&#34;&gt;https://github.com/stevapple/swiftbox&lt;/a&gt;&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;cd ~/$DESIRED_PATH
git clone https://github.com/carlynorama/SketchPad.git
cd SketchPad
swift run sketchpad multiball -s
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;All good!&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;runs_on_linux.png&#34; alt=&#34;Screenshot of the Linux virtual machine with a VSCode window open to the SketchPad project with a freshly minted .usda file.&#34;&gt;&lt;/p&gt;
</description>
    </item>
    
    
    
    <item>
      <title>Hello USD - Part 13: Test, Test, Test</title>
      <link>https://whynotestflight.com/excuses/hello-usd-part-13-test-test-test/</link>
      <pubDate>Wed, 19 Jul 2023 00:00:00 +0000</pubDate>
      
      <guid>https://whynotestflight.com/excuses/hello-usd-part-13-test-test-test/</guid>
      <description>&lt;p&gt;&amp;ldquo;The best time to build a test was before the first commit. The next best time is now.&amp;rdquo; &amp;ndash; Proverbious the Commitor, probably&lt;/p&gt;
&lt;p&gt;The SketchPad output needs to be validated on three levels:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Is my code making the &lt;code&gt;.usda&lt;/code&gt; files I think it should be?  (XCTests)&lt;/li&gt;
&lt;li&gt;Does my code compile on Linux? (VM and GitHub CI test)&lt;/li&gt;
&lt;li&gt;Are my &lt;code&gt;.usda&lt;/code&gt; files correct according to &lt;code&gt;usdchecker&lt;/code&gt;?&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This posts documents setting up unit tests, which I&amp;rsquo;ll use to address the first step.&lt;/p&gt;
&lt;h3 id=&#34;overviews&#34;&gt;Overviews&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://developer.apple.com/documentation/xctest&#34;&gt;https://developer.apple.com/documentation/xctest&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://www.hackingwithswift.com/read/39/2/creating-our-first-unit-test-using-xctest&#34;&gt;https://www.hackingwithswift.com/read/39/2/creating-our-first-unit-test-using-xctest&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://www.avanderlee.com/swift/unit-tests-best-practices/&#34;&gt;https://www.avanderlee.com/swift/unit-tests-best-practices/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://www.swiftbysundell.com/articles/test-assertions-in-swift/&#34;&gt;https://www.swiftbysundell.com/articles/test-assertions-in-swift/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://www.vadimbulavin.com/unit-testing-best-practices-on-ios-with-swift/&#34;&gt;https://www.vadimbulavin.com/unit-testing-best-practices-on-ios-with-swift/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;update-package-file-and-make-tests-directory&#34;&gt;Update Package File and Make Tests Directory&lt;/h2&gt;
&lt;p&gt;Update package file and create a new directory&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#91d7e3&#34;&gt;cd&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;$PROJECT_DIR&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;mkdir Tests
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;touch Tests/FileBuilderTests/MyFirstTest.swift
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;├── Package.swift
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;├── README.md
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;├── Sources
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;│   └── &amp;lt;Source Files&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;└── Tests
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    └── FileBuilderTests
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        └── MyFirstTest.swift
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    targets: [
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        .target(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            name: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;SketchPad&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        ),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        .testTarget(name: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;FileBuilderTests&amp;#34;&lt;/span&gt;, dependencies: [&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;SketchPad&amp;#34;&lt;/span&gt;]),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        .executableTarget(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            name: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;SketchPadCLI&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            dependencies: [
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;SketchPad&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                .product(name: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;ArgumentParser&amp;#34;&lt;/span&gt;, package: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;swift-argument-parser&amp;#34;&lt;/span&gt;),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            ]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        )
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    ]
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;test-that-tests-run&#34;&gt;Test That Tests Run&lt;/h2&gt;
&lt;p&gt;The basic Test template for a package that Xcode auto-generates looks like:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;XCTest&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;@testable &lt;span style=&#34;color:#ed8796&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;$&lt;/span&gt;&lt;span style=&#34;color:#eed49f&#34;&gt;LIBRARY_NAME&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;final&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;SomeNameTests&lt;/span&gt;: XCTestCase {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;testExample&lt;/span&gt;() &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// This is an example of a functional test case.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// Use XCTAssert and related functions to verify your tests produce the correct&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// results.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        XCTAssertEqual(&lt;span style=&#34;color:#ed8796&#34;&gt;$&lt;/span&gt;SOME_TEXT_VAR, &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Hello, World!&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;@testable&lt;/code&gt; makes functions that would normally not be available outside the package available for testing. Which I know I want in this case.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;m starting with the below, a guaranteed pass to make sure everything works.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;XCTest&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;@testable &lt;span style=&#34;color:#ed8796&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;SketchPad&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;final&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;FileBuilderTests&lt;/span&gt;: XCTestCase {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;testExample&lt;/span&gt;() &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        XCTAssertEqual(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Hello, World!&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Hello, World!&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Then ran the tests from the command line with:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;swift test
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Generating the following in the console:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Building for debugging...
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;[4/4] Linking SketchPadPackageTests
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Build complete! (0.70s)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Test Suite &amp;#39;All tests&amp;#39; started at 2023-07-18 10:42:38.303
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Test Suite &amp;#39;SketchPadPackageTests.xctest&amp;#39; started at 2023-07-18 10:42:38.304
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Test Suite &amp;#39;FileBuilderTests&amp;#39; started at 2023-07-18 10:42:38.304
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Test Case &amp;#39;-[FileBuilderTests.FileBuilderTests testExample]&amp;#39; started.
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Test Case &amp;#39;-[FileBuilderTests.FileBuilderTests testExample]&amp;#39; passed (0.001 seconds).
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Test Suite &amp;#39;FileBuilderTests&amp;#39; passed at 2023-07-18 10:42:38.305.
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;         Executed 1 test, with 0 failures (0 unexpected) in 0.001 (0.001) seconds
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Test Suite &amp;#39;SketchPadPackageTests.xctest&amp;#39; passed at 2023-07-18 10:42:38.305.
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;         Executed 1 test, with 0 failures (0 unexpected) in 0.001 (0.001) seconds
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Test Suite &amp;#39;All tests&amp;#39; passed at 2023-07-18 10:42:38.305.
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;         Executed 1 test, with 0 failures (0 unexpected) in 0.001 (0.002) seconds
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Note that the command ran All the tests. In the future I will not want to run all the tests all the time. I&amp;rsquo;ll be able to run just a subset with:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;swift &lt;span style=&#34;color:#91d7e3&#34;&gt;test&lt;/span&gt; --filter &lt;span style=&#34;color:#f4dbd6&#34;&gt;$TEST_TARGET_NAME&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## For example:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;swift &lt;span style=&#34;color:#91d7e3&#34;&gt;test&lt;/span&gt; --filter FileBuilderTests
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now let&amp;rsquo;s see what what happens after adding a mismatch to the test and running just the &lt;code&gt;FileBuilderTests&lt;/code&gt; target.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;XCTest&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;@testable &lt;span style=&#34;color:#ed8796&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;SketchPad&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;final&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;FileBuilderTests&lt;/span&gt;: XCTestCase {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;testExample&lt;/span&gt;() &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        XCTAssertEqual(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Hello, Dolly!&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Hello, World!&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&amp;hellip; the output will be:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Building for debugging...
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;[4/4] Linking SketchPadPackageTests
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Build complete! (0.69s)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Test Suite &amp;#39;Selected tests&amp;#39; started at 2023-07-18 10:51:53.822
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Test Suite &amp;#39;SketchPadPackageTests.xctest&amp;#39; started at 2023-07-18 10:51:53.823
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Test Suite &amp;#39;FileBuilderTests&amp;#39; started at 2023-07-18 10:51:53.823
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Test Case &amp;#39;-[FileBuilderTests.FileBuilderTests testExample]&amp;#39; started.
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;/Users/carlynorama/Developer/GitHub/SketchPad/Tests/FileBuilderTests/MyFirstTest.swift:16: error: -[FileBuilderTests.FileBuilderTests testExample] : XCTAssertEqual failed: (&amp;#34;Hello, Dolly!&amp;#34;) is not equal to (&amp;#34;Hello, World!&amp;#34;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Test Case &amp;#39;-[FileBuilderTests.FileBuilderTests testExample]&amp;#39; failed (0.012 seconds).
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Test Suite &amp;#39;FileBuilderTests&amp;#39; failed at 2023-07-18 10:51:53.835.
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;         Executed 1 test, with 1 failure (0 unexpected) in 0.012 (0.012) seconds
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Test Suite &amp;#39;SketchPadPackageTests.xctest&amp;#39; failed at 2023-07-18 10:51:53.835.
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;         Executed 1 test, with 1 failure (0 unexpected) in 0.012 (0.012) seconds
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Test Suite &amp;#39;Selected tests&amp;#39; failed at 2023-07-18 10:51:53.835.
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;         Executed 1 test, with 1 failure (0 unexpected) in 0.012 (0.013) seconds
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;That&amp;rsquo;s still a lot to go digging through to find the error.&lt;/p&gt;
&lt;h2 id=&#34;setting-up-xcode-to-test-a-package&#34;&gt;Setting up XCode to Test a Package&lt;/h2&gt;
&lt;p&gt;I&amp;rsquo;ve been doing all my building for this project in the command line using &lt;code&gt;swift run&lt;/code&gt;. Seeing the dense results of &lt;code&gt;swift test&lt;/code&gt; makes me want to run to XCode to scan for those &lt;a href=&#34;https://www.hackingwithswift.com/read/39/2/creating-our-first-unit-test-using-xctest&#34;&gt;little red diamonds&lt;/a&gt; when they crop up.&lt;/p&gt;
&lt;p&gt;Since I added the &lt;code&gt;testTarget&lt;/code&gt; by hand, for XCode I needed to also add a &lt;a href=&#34;https://developer.apple.com/documentation/xcode/customizing-the-build-schemes-for-a-project/&#34;&gt;Scheme&lt;/a&gt; by hand as well. To do so through the menu choose &lt;code&gt;Product &amp;gt; Scheme &amp;gt; New Scheme&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;New Schema&lt;/code&gt; window&amp;rsquo;s dropdown menu already showed &lt;code&gt;FileBuildTests&lt;/code&gt; as selected. Leaving the name unchanged, I hit OK. Once setting the active Schema to FileBuildTests, I then had no problems running a test by clicking on the diamond in the number gutter next to its declaration.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;schemeSelector.png&#34; alt=&#34;Cropped screenshot of the area at the top of an XCode window where one can select the Scheme&#34;&gt;&lt;/p&gt;
&lt;p&gt;Switching the selected Scheme to the cli (&lt;code&gt;sketchpad&lt;/code&gt;) would let me run the default script by pressing the Run button. By default the the output goes to the console.  I played around with adding a &lt;a href=&#34;https://www.kodeco.com/511-command-line-programs-on-macos-tutorial#toc-anchor-007&#34;&gt;shortcut to open terminal&lt;/a&gt;, but had no luck setting up the XCode Scheme to receive a command or options arguments. YMMV.&lt;/p&gt;
&lt;h2 id=&#34;first-actually-useful-test&#34;&gt;First Actually Useful Test&lt;/h2&gt;
&lt;p&gt;I changed the name of the file to &lt;code&gt;HelperStructsTests.swift&lt;/code&gt; and began writing the tests for &lt;code&gt;Document&lt;/code&gt;.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;XCTest&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;@testable &lt;span style=&#34;color:#ed8796&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;SketchPad&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;final&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;DocumentTests&lt;/span&gt;: XCTestCase {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;testExample&lt;/span&gt;() &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;result&lt;/span&gt; = Document {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Hello, 
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;            World!&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        XCTAssertEqual(result.render(style: .minimal), &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Hello, World!&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;I&amp;rsquo;ll eventually match each file in Sources with a file in Tests.&lt;/p&gt;
&lt;p&gt;&amp;lt; INSERT TEST WRITING MONTAGE, with motivational music of course &amp;gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://github.com/carlynorama/SketchPad/tree/main/Tests/FileBuilderTests&#34;&gt;https://github.com/carlynorama/SketchPad/tree/main/Tests/FileBuilderTests&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&#34;lessons-learned&#34;&gt;Lessons learned&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;TODO: Both Braced and Document have opinions about formatting.  Can both be in control of formatting? Writing the tests made me realize Documents &lt;code&gt;.minimal&lt;/code&gt; always wins over the CurlyBraced preference. Is that what I want? I think so?&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Dictionary backed &lt;code&gt;Strings&lt;/code&gt; require a bit of fancy footwork to test. Neither XML nor USD care about the order of meta information in certain contexts, so I used Dictionaries. Hard to write test code of a string that might change it&amp;rsquo;s order (size of Dictionary^2). I finally busted out RegexBuilder. TBD if I think this is good practice?&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;XCTest&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;@testable &lt;span style=&#34;color:#ed8796&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;SketchPad&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;RegexBuilder&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;final&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;USDFileBuilderTests&lt;/span&gt;: XCTestCase {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;defaultBuilder&lt;/span&gt; = USDAFileBuilder()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    @available(macOS &lt;span style=&#34;color:#f5a97f&#34;&gt;13.0&lt;/span&gt;, &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;*&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;headerMatch&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; toTest:&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;) -&amp;gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;Bool&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;regex&lt;/span&gt; = Regex {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            One(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;#usda 1.0&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\n&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\n\t&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            OneOrMore(.any)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            One(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\n&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;)&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; toTest.firstMatch(of: regex) &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;!=&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;nil&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;true&lt;/span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;false&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    @available(macOS &lt;span style=&#34;color:#f5a97f&#34;&gt;13.0&lt;/span&gt;, &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;*&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;test_getHeaderStructure&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;documentRender&lt;/span&gt; = Document {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#f5a97f&#34;&gt;Self&lt;/span&gt;.defaultBuilder.generateHeader(defaultPrimID: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;MyPrim&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }.render(style: .multilineIndented)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;testResult&lt;/span&gt; = headerMatch(documentRender)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        XCTAssert(testResult)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        XCTAssert(documentRender.&lt;span style=&#34;color:#91d7e3&#34;&gt;contains&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;defaultPrim =&amp;#34;&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        XCTAssert(documentRender.&lt;span style=&#34;color:#91d7e3&#34;&gt;contains&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;upAxis =&amp;#34;&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        XCTAssert(documentRender.&lt;span style=&#34;color:#91d7e3&#34;&gt;contains&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;metersPerUnit =&amp;#34;&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ul&gt;
&lt;li&gt;In order to compare two StringNodes in a test, StringNode has to be Equatable. (&lt;code&gt;Hashable&lt;/code&gt; comes for free because only Strings involved)&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;extension&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;StringNode&lt;/span&gt;: &lt;span style=&#34;color:#91d7e3&#34;&gt;Equatable&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; == (lhs: StringNode, rhs: StringNode) -&amp;gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;Bool&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;switch&lt;/span&gt; (lhs, rhs) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;case&lt;/span&gt; (.container(&lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;lhs&lt;/span&gt;), .container(&lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;rhs&lt;/span&gt;)):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; lhs == rhs
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;case&lt;/span&gt; (.content(&lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;lhs&lt;/span&gt;), .content(&lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;rhs&lt;/span&gt;)):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; lhs == rhs
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;case&lt;/span&gt; (.list(&lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;lhs&lt;/span&gt;), .list(&lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;rhs&lt;/span&gt;)):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; lhs == rhs
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;default&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;false&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;difficulty-with-finding-out-code-coverage-unresolved&#34;&gt;Difficulty With Finding out Code Coverage (unresolved)&lt;/h3&gt;
&lt;p&gt;Can&amp;rsquo;t really figure out how to gauge my coverage.  Not that worried about it, but do love a data point.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://stackoverflow.com/questions/76192332/how-can-i-enable-code-coverage-in-xcode-14-3-it-appears-different-from-other-v&#34;&gt;https://stackoverflow.com/questions/76192332/how-can-i-enable-code-coverage-in-xcode-14-3-it-appears-different-from-other-v&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;TODO? : &lt;a href=&#34;https://github.com/Nef10/swift-test-coverage&#34;&gt;https://github.com/Nef10/swift-test-coverage&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;reference-dump&#34;&gt;Reference Dump&lt;/h2&gt;
&lt;h3 id=&#34;misc--future-topics&#34;&gt;Misc &amp;amp; Future Topics&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://mokacoding.com/blog/how-to-write-tests-for-swift-result/&#34;&gt;https://mokacoding.com/blog/how-to-write-tests-for-swift-result/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://forums.swift.org/t/swiftpm-and-library-unit-testing/26255/11&#34;&gt;https://forums.swift.org/t/swiftpm-and-library-unit-testing/26255/11&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://alexanderweiss.dev/blog/2021-05-15-add-test-data-to-spm-packages&#34;&gt;https://alexanderweiss.dev/blog/2021-05-15-add-test-data-to-spm-packages&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://www.vadimbulavin.com/unit-testing-async-code-in-swift/&#34;&gt;https://www.vadimbulavin.com/unit-testing-async-code-in-swift/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-swift&#34;&gt;https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-swift&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://forums.swift.org/t/linking-process-in-swift-build-vs-xcode-build/39777&#34;&gt;https://forums.swift.org/t/linking-process-in-swift-build-vs-xcode-build/39777&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://www.vadimbulavin.com/swift-asynchronous-unit-testing-with-busy-assertion-pattern/&#34;&gt;https://www.vadimbulavin.com/swift-asynchronous-unit-testing-with-busy-assertion-pattern/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://developer.apple.com/documentation/xcode/writing-and-running-performance-tests&#34;&gt;https://developer.apple.com/documentation/xcode/writing-and-running-performance-tests&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</description>
    </item>
    
    
    
    <item>
      <title>Hello USD - Part 12: Lets make these FileBuilders cleaner</title>
      <link>https://whynotestflight.com/excuses/hello-usd-part-12-lets-make-these-filebuilders-cleaner/</link>
      <pubDate>Tue, 18 Jul 2023 00:00:00 +0000</pubDate>
      
      <guid>https://whynotestflight.com/excuses/hello-usd-part-12-lets-make-these-filebuilders-cleaner/</guid>
      <description>&lt;p&gt;Currently both USDFileBuilder and X3DFileBuilder rely on &lt;code&gt;MultiLineStringBuilder&lt;/code&gt;, which newly ignores empty lines from the previous version of &lt;code&gt;StringBuilder&lt;/code&gt; shown in &lt;a href=&#34;https://whynotestflight.com/excuses/hello-usd-part-8-multiball-moves-to-a-package/&#34;&gt;Part 8&lt;/a&gt; I need to change these to use the &lt;code&gt;StringNodeBuilder&lt;/code&gt; instead.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;@resultBuilder
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;MultiLineStringBuilder&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;buildBlock&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; parts: &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;...) -&amp;gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        buildArray(parts)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;buildOptional&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; component:&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;?) -&amp;gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        component ?? &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;buildEither&lt;/span&gt;(&lt;span style=&#34;color:#91d7e3&#34;&gt;first&lt;/span&gt; component: &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;) -&amp;gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; component
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;buildEither&lt;/span&gt;(second component: &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;) -&amp;gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; component
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;buildArray&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; components: [&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;]) -&amp;gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        components.&lt;span style=&#34;color:#91d7e3&#34;&gt;filter&lt;/span&gt;( { &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;!&lt;/span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;$0&lt;/span&gt;.&lt;span style=&#34;color:#91d7e3&#34;&gt;isEmpty&lt;/span&gt; } ).joined(separator: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\n&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;starting-off&#34;&gt;Starting Off&lt;/h2&gt;
&lt;p&gt;First steps:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Copy the code from yesterday into a new file in SketchPad.&lt;/li&gt;
&lt;li&gt;Clean out the extras&lt;/li&gt;
&lt;li&gt;Change the name of Nodeable -&amp;gt; StringNodeable&lt;/li&gt;
&lt;li&gt;rewrite &lt;code&gt;generateStringForStage&lt;/code&gt; using the &lt;code&gt;Document&lt;/code&gt; type.&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//X3D&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;generateStringForStage&lt;/span&gt;(stage:Canvas3D) -&amp;gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;document&lt;/span&gt; = Document {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            generateHeader()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            sceneHeader()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;for&lt;/span&gt; item &lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt; stage.content {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                sphereBuilder(shape: item)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            sceneFooter()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            pageFooter()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; document.render(style: .indented)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//USD&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;generateStringForStage&lt;/span&gt;(stage:Canvas3D) -&amp;gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;document&lt;/span&gt; = Document {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            generateHeader(defaultPrimID:stage.content[defaultPrimIndex].id)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;for&lt;/span&gt; item &lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt; stage.content {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                sphereBuilder(shape: item)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; document.render(style: .indented)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Worked as expected.  &lt;a href=&#34;first_output.txt&#34;&gt;first output&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Next came the painstaking process of replacing every reference to &lt;code&gt;@MultiLineStringBuilder&lt;/code&gt; function returning a String with something that would return a &lt;code&gt;StringNodeable&lt;/code&gt; instead.&lt;/p&gt;
&lt;h2 id=&#34;refactoring-the-usdfilebuilder&#34;&gt;Refactoring the USDFileBuilder&lt;/h2&gt;
&lt;p&gt;Let&amp;rsquo;s start off by looking at what happened to &lt;code&gt;sphereBuilder&lt;/code&gt;&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    @MultiLineBuilder &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;sphereBuilder&lt;/span&gt;(shape:Sphere) -&amp;gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;def Xform &lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;shape.id&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\&amp;#34;\n&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;{&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//&amp;#34;def Xform \&amp;#34;\(shape.shapeName)_\(shape.id)\&amp;#34;\n{&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;!&lt;/span&gt;shape.transformations.&lt;span style=&#34;color:#91d7e3&#34;&gt;isEmpty&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            transformString(shape:shape) 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//&amp;#34;\tdef \(shape.shapeName) \&amp;#34;\(shape.shapeName.lowercased())_\(shape.id)\&amp;#34;\n\t{&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\t&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;def &lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;shape.shapeName&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;shape.id.lowercased&lt;span style=&#34;color:#a6da95&#34;&gt;())&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\&amp;#34;\n\t&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;{&amp;#34;&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\t\t&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;extentString&lt;span style=&#34;color:#a6da95&#34;&gt;(&lt;/span&gt;shape: shape&lt;span style=&#34;color:#a6da95&#34;&gt;))&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;!&lt;/span&gt;shape.surfaces.&lt;span style=&#34;color:#91d7e3&#34;&gt;isEmpty&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            colorString(shape:shape)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\t\t&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;radiusString&lt;span style=&#34;color:#a6da95&#34;&gt;(&lt;/span&gt;shape.radius&lt;span style=&#34;color:#a6da95&#34;&gt;))&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\t&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;}&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;}&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Becomes:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;sphereBuilder&lt;/span&gt;(shape:Sphere) -&amp;gt; StringNodeable {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        CurlyBraced(opening: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;def Xform &lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;shape.id&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;!&lt;/span&gt;shape.transformations.&lt;span style=&#34;color:#91d7e3&#34;&gt;isEmpty&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                transformString(shape:shape)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            CurlyBraced(opening: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;def &lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;shape.shapeName&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;shape.id.lowercased&lt;span style=&#34;color:#a6da95&#34;&gt;())&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;extentString&lt;span style=&#34;color:#a6da95&#34;&gt;(&lt;/span&gt;shape: shape&lt;span style=&#34;color:#a6da95&#34;&gt;))&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;!&lt;/span&gt;shape.surfaces.&lt;span style=&#34;color:#91d7e3&#34;&gt;isEmpty&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    colorString(shape:shape)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;radiusString&lt;span style=&#34;color:#a6da95&#34;&gt;(&lt;/span&gt;shape.radius&lt;span style=&#34;color:#a6da95&#34;&gt;))&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;No more &lt;code&gt;\t&lt;/code&gt;, &lt;code&gt;\n&lt;/code&gt;, no more &lt;code&gt;{&lt;/code&gt; or &lt;code&gt;}&lt;/code&gt; manually written in to any of the strings with the help of a new struct &lt;code&gt;CurlyBraced&lt;/code&gt;.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;CurlyBraced&lt;/span&gt;:StringNodeable {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;prefix&lt;/span&gt;: &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;suffix&lt;/span&gt;: &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt; = &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;}&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;content&lt;/span&gt;: StringNode
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;init&lt;/span&gt;(opening:&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;, @StringNodeBuilder content: () -&amp;gt; [StringNode]) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;.&lt;span style=&#34;color:#c6a0f6&#34;&gt;prefix&lt;/span&gt; = &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;opening&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt; {&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;.content = .list(content())
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;asStringNode&lt;/span&gt;: StringNode {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        .container((&lt;span style=&#34;color:#c6a0f6&#34;&gt;prefix&lt;/span&gt;: &lt;span style=&#34;color:#c6a0f6&#34;&gt;prefix&lt;/span&gt;, content: content, &lt;span style=&#34;color:#91d7e3&#34;&gt;suffix&lt;/span&gt;: &lt;span style=&#34;color:#91d7e3&#34;&gt;suffix&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;I could write custom &lt;code&gt;struct&lt;/code&gt;&amp;rsquo;s for each component of a USD file, but at this stage of the game, thats a lot of lines of very similar looking code for not a lot of payoff.&lt;/p&gt;
&lt;p&gt;On the other hand, since &lt;code&gt;.usd&lt;/code&gt; files use both curly braces and parentheses, abstracting out a &amp;ldquo;Bracing&amp;rdquo; protocol made sense. I also added whitespace style choices: compact, semiCompact and expanded. USD files tend to use the expanded format with opening and closing braces on their own lines.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;enum&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;BraceSpacingStyle&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;case&lt;/span&gt; compact, semiCompact, expanded
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;protocol&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;Bracing&lt;/span&gt;:StringNodeable {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;braceOpener&lt;/span&gt;:&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt; { &lt;span style=&#34;color:#c6a0f6&#34;&gt;get&lt;/span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;braceCloser&lt;/span&gt;:&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt; { &lt;span style=&#34;color:#c6a0f6&#34;&gt;get&lt;/span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;precedingText&lt;/span&gt;:&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;? { &lt;span style=&#34;color:#c6a0f6&#34;&gt;get&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;set&lt;/span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;content&lt;/span&gt;: StringNode { &lt;span style=&#34;color:#c6a0f6&#34;&gt;get&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;set&lt;/span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;style&lt;/span&gt;:BraceSpacingStyle { &lt;span style=&#34;color:#c6a0f6&#34;&gt;get&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;set&lt;/span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;asStringNode&lt;/span&gt;: StringNode { &lt;span style=&#34;color:#c6a0f6&#34;&gt;get&lt;/span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;} 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;extension&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;Bracing&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;asStringNode&lt;/span&gt;: StringNode {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;switch&lt;/span&gt; style {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;case&lt;/span&gt; .expanded:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;guard&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;precedingText&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#c6a0f6&#34;&gt;fallthrough&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; .list([
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                .content(precedingText),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                .container((&lt;span style=&#34;color:#c6a0f6&#34;&gt;prefix&lt;/span&gt;: braceOpener, content: content, &lt;span style=&#34;color:#91d7e3&#34;&gt;suffix&lt;/span&gt;: braceCloser))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            ])
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;case&lt;/span&gt; .semiCompact:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;start&lt;/span&gt; = precedingText &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;!=&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;nil&lt;/span&gt; ? &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;precedingText!&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;braceOpener&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt; : &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;braceOpener&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; .container((&lt;span style=&#34;color:#c6a0f6&#34;&gt;prefix&lt;/span&gt;: start, content: content, &lt;span style=&#34;color:#91d7e3&#34;&gt;suffix&lt;/span&gt;: braceCloser))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;case&lt;/span&gt; .compact:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;contentString&lt;/span&gt; = StringNode.stringify(node:content)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; .content(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;precedingText ?? &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;)\(&lt;/span&gt;braceOpener&lt;span style=&#34;color:#a6da95&#34;&gt;)\(&lt;/span&gt;contentString&lt;span style=&#34;color:#a6da95&#34;&gt;)\(&lt;/span&gt;braceCloser&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;CurlyBraced&lt;/span&gt;:Bracing {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;braceOpener&lt;/span&gt;:&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt; = &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;{&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;braceCloser&lt;/span&gt;:&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt; = &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;}&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;precedingText&lt;/span&gt;: &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;?
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;style&lt;/span&gt;: BraceSpacingStyle
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;content&lt;/span&gt;: StringNode
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;init&lt;/span&gt;(opening:&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;? = &lt;span style=&#34;color:#f5a97f&#34;&gt;nil&lt;/span&gt;, style:BraceSpacingStyle = .semiCompact, @StringNodeBuilder content: () -&amp;gt; [StringNode]) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;.precedingText = opening
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;.content = .list(content())
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;.style = style
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;Parens&lt;/span&gt;:Bracing {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;braceOpener&lt;/span&gt;:&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt; = &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;(&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;braceCloser&lt;/span&gt;:&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt; = &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;)&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;precedingText&lt;/span&gt;: &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;?
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;style&lt;/span&gt;: BraceSpacingStyle
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;content&lt;/span&gt;: StringNode
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;init&lt;/span&gt;(opening:&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;? = &lt;span style=&#34;color:#f5a97f&#34;&gt;nil&lt;/span&gt;, style:BraceSpacingStyle = .semiCompact, @StringNodeBuilder content: () -&amp;gt; [StringNode]) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;.precedingText = opening
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;.content = .list(content())
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;.style = style
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ul&gt;
&lt;li&gt;TODO: see if I could somehow include the init in the protocol. Or yet another candidate for a macro?&lt;/li&gt;
&lt;li&gt;TODO: What if content is empty or only 1 item? Does it matter?&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;With all that implemented my generateHeader function can now look like:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;generateHeader&lt;/span&gt;(defaultPrimID:&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                        fileType:&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt; = &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;usda&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                        version:&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt; = &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;1.0&amp;#34;&lt;/span&gt;) -&amp;gt; StringNode {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;metaData&lt;/span&gt; = [
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;defaultPrim&amp;#34;&lt;/span&gt;:defaultPrimID.quoted(),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;metersPerUnit&amp;#34;&lt;/span&gt;:&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;metersPerUnit&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;upAxis&amp;#34;&lt;/span&gt;:upAxis.quoted()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        ]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;documentationNote&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            metaData[&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;documentationNote&amp;#34;&lt;/span&gt;] = documentationNote
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; Parens(opening: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;#&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;fileType&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;version&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;, 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    style: .expanded,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    content: { .list(dictionaryToEqualSigns(dict: metaData)) } 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                ).asStringNode
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;dictionaryToEqualSigns&lt;/span&gt;(dict:&lt;span style=&#34;color:#91d7e3&#34;&gt;Dictionary&lt;/span&gt;&amp;lt;&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;,&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;&amp;gt;) -&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    [StringNode] {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;tmp&lt;/span&gt;:[StringNode] = []
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;for&lt;/span&gt; (key, value) &lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt; dict {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            tmp.append(.content(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;key&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt; = &lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;value&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; tmp
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Note the dictionary based metadata generator waiting to for a time when I might have other things to add. (It gets updated at the end of this post.)&lt;/p&gt;
&lt;p&gt;Also a project level &lt;code&gt;String&lt;/code&gt; extension will help make adding escaped quotes easier.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;extension&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;String&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;brace&lt;/span&gt;(with e:&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;) -&amp;gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;e&lt;span style=&#34;color:#a6da95&#34;&gt;)\(&lt;/span&gt;&lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;)\(&lt;/span&gt;e&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;quoted&lt;/span&gt;()  -&amp;gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        brace(with:&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;To generate:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-usd&#34; data-lang=&#34;usd&#34;&gt;#usda 1.0
(
	upAxis = &amp;#34;Y&amp;#34;
	defaultPrim = &amp;#34;Sphere_53140&amp;#34;
	metersPerUnit = 1
)
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&#34;refactoring-the-x3dfilebuilder&#34;&gt;Refactoring the X3DFileBuilder&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;X3D&lt;/code&gt; is &lt;code&gt;XML&lt;/code&gt;, which has tags, not braces.  Tags, like the metadata in USD files, can make attributes from a varying number of key value pairs, so again I use a dictionary to drive the &lt;code&gt;String&lt;/code&gt; creation.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;Tag&lt;/span&gt;:StringNodeable {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;name&lt;/span&gt;:&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;attributes&lt;/span&gt;:&lt;span style=&#34;color:#91d7e3&#34;&gt;Dictionary&lt;/span&gt;&amp;lt;&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;, &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;&amp;gt;?
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;prefix&lt;/span&gt;: &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt; { 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;attributes&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&amp;lt;&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;name&lt;span style=&#34;color:#a6da95&#34;&gt;)\(&lt;/span&gt;&lt;span style=&#34;color:#f5a97f&#34;&gt;Self&lt;/span&gt;.attributesFromDictionary&lt;span style=&#34;color:#a6da95&#34;&gt;(&lt;/span&gt;attributes&lt;span style=&#34;color:#a6da95&#34;&gt;))&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        } &lt;span style=&#34;color:#c6a0f6&#34;&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&amp;lt;&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;name&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;gt;&amp;#34;&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;suffix&lt;/span&gt;: &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt; { &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&amp;lt;/&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;name&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;gt;&amp;#34;&lt;/span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;content&lt;/span&gt;: StringNode
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;init&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; name:&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;, attributes:&lt;span style=&#34;color:#91d7e3&#34;&gt;Dictionary&lt;/span&gt;&amp;lt;&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;, &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;&amp;gt;? = &lt;span style=&#34;color:#f5a97f&#34;&gt;nil&lt;/span&gt;, @StringNodeBuilder content: () -&amp;gt; [StringNode]) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;.name = name
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;.attributes = attributes
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;.content = .list(content())
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;asStringNode&lt;/span&gt;: StringNode {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        .container((&lt;span style=&#34;color:#c6a0f6&#34;&gt;prefix&lt;/span&gt;: &lt;span style=&#34;color:#c6a0f6&#34;&gt;prefix&lt;/span&gt;, content: content, &lt;span style=&#34;color:#91d7e3&#34;&gt;suffix&lt;/span&gt;: &lt;span style=&#34;color:#91d7e3&#34;&gt;suffix&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;extension&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;Tag&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;attributesFromDictionary&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; dict:&lt;span style=&#34;color:#91d7e3&#34;&gt;Dictionary&lt;/span&gt;&amp;lt;&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;, &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;&amp;gt;) -&amp;gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;tmp&lt;/span&gt;:&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt; = &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;for&lt;/span&gt; (key, value) &lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt; dict {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            tmp.append(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34; &lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;key&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;value.embrace&lt;span style=&#34;color:#a6da95&#34;&gt;(&lt;/span&gt;with: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&amp;#39;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;))&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; tmp
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;That helper struct let me refactor the&lt;code&gt;sphereBuilder&lt;/code&gt; from:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;@StringBuilder &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;sphereBuilder&lt;/span&gt;(shape:Sphere) -&amp;gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;!&lt;/span&gt;shape.transformations.&lt;span style=&#34;color:#91d7e3&#34;&gt;isEmpty&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;for&lt;/span&gt; transform &lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt; shape.transformations {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            transformStart(transform:transform)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&amp;lt;shape&amp;gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\t&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;lt;appearance&amp;gt;&amp;#34;&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;!&lt;/span&gt;shape.surfaces.&lt;span style=&#34;color:#91d7e3&#34;&gt;isEmpty&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        materialString(shape.surfaces)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\t&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;lt;/appearance&amp;gt;&amp;#34;&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\t&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;lt;sphere radius=&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;shape.radius&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#39;&amp;gt;&amp;lt;/sphere&amp;gt;&amp;#34;&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&amp;lt;/shape&amp;gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;!&lt;/span&gt;shape.transformations.&lt;span style=&#34;color:#91d7e3&#34;&gt;isEmpty&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;for&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;0.&lt;/span&gt;.&amp;lt;shape.transformations.&lt;span style=&#34;color:#91d7e3&#34;&gt;count&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            transformClose()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;transformStart&lt;/span&gt;(transform:Transformation) -&amp;gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;switch&lt;/span&gt; transform {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;case&lt;/span&gt; .translate(&lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;v&lt;/span&gt;):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&amp;lt;transform translation=&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;v.x&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;v.y&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;v.z&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#39;&amp;gt;&amp;#34;&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// default:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// fatalError()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;transformClose&lt;/span&gt;() -&amp;gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&amp;lt;/transform&amp;gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;To:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;sphereBuilder&lt;/span&gt;(shape:Sphere) -&amp;gt; StringNodeable {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;content&lt;/span&gt; = Tag(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Shape&amp;#34;&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            Tag(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Appearance&amp;#34;&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;!&lt;/span&gt;shape.surfaces.&lt;span style=&#34;color:#91d7e3&#34;&gt;isEmpty&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//function unchanged from previous code for now&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//still needs updating at this point.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    materialString(shape.surfaces)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&amp;lt;Sphere radius=&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;shape.radius&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#39;&amp;gt;&amp;lt;/Sphere&amp;gt;&amp;#34;&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;!&lt;/span&gt;shape.transformations.&lt;span style=&#34;color:#91d7e3&#34;&gt;isEmpty&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//Last closest to the content.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;orderedTransforms&lt;/span&gt; = shape.transformations.reversed()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;for&lt;/span&gt; item &lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt; orderedTransforms {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;attributes&lt;/span&gt; = transformAttribute(transform: item)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                content = Tag(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Transform&amp;#34;&lt;/span&gt;, attributes:attributes) { content }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        } 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; content
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;transformAttribute&lt;/span&gt;(transform:Transformation) -&amp;gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;Dictionary&lt;/span&gt;&amp;lt;&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;,&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;&amp;gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;switch&lt;/span&gt; transform {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;case&lt;/span&gt; .translate(&lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;v&lt;/span&gt;):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; [&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;translation&amp;#34;&lt;/span&gt;:&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;v.x&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;v.y&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;v.z&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;] 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;one-last-thing&#34;&gt;One last thing&amp;hellip;&lt;/h2&gt;
&lt;p&gt;Added to USDBuilder&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;fileprivate &lt;span style=&#34;color:#ed8796&#34;&gt;extension&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;Dictionary&lt;/span&gt;&amp;lt;&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;, &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;&amp;gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;equalSigns&lt;/span&gt;() -&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    [&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;] {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;tmp&lt;/span&gt;:[&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;] = []
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;for&lt;/span&gt; (key, value) &lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            tmp.append(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;key&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt; = &lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;value&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; tmp
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now allows me to write the return of USDBuilder&amp;rsquo;s generateHeader all the more cleanly.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; Parens(opening: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;#&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;fileType&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;version&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;, 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    style: .expanded,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    content: {  metaData.equalSigns() }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    )
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;I gave the same treatment to few functions that were formatting dictionaries. I marked them as file private because different FileBuilders will have different needs.&lt;/p&gt;
&lt;h2 id=&#34;next-steps&#34;&gt;Next Steps&lt;/h2&gt;
&lt;p&gt;One could spend a very long time writing custom file builders with type safe specialized tags, etc. That&amp;rsquo;s not the goal here because my source of truth for these will always be a strongly typed data structure.  I&amp;rsquo;ve already in &lt;a href=&#34;https://github.com/carlynorama/APItizer/&#34;&gt;APItizer&lt;/a&gt; worked with turning &lt;code&gt;structs&lt;/code&gt; &lt;a href=&#34;https://github.com/carlynorama/APItizer/blob/main/Sources/APItizer/Encoding/DictionaryEncoder.swift&#34;&gt;into Dictionaries&lt;/a&gt; if I end up needing that.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;m pleased enough with the improved ergonomics for writing file builders that I can take a chip at my next task: &lt;code&gt;.usda&lt;/code&gt; file validation.&lt;/p&gt;
&lt;p&gt;Before my files get too fancy, I&amp;rsquo;d like to figure out how to submit my USD files to &lt;code&gt;usdchecker&lt;/code&gt; automatically on creation so I get instant warning if something goes wrong. In an amazing world I&amp;rsquo;d be able to do that as part of &lt;code&gt;XCTest&lt;/code&gt;, but one step at a time.&lt;/p&gt;
&lt;!-- Note: The Max Count for multiball is 299 spheres. --&gt;
&lt;!-- &lt;script type=&#39;text/javascript&#39; src=&#39;https://www.x3dom.org/download/x3dom.js&#39;&gt; &lt;/script&gt; 
&lt;x3d width=&#39;500px&#39; height=&#39;400px&#39;&gt; 
&lt;scene&gt;
&lt;inline url=&#34;too_many_test.x3d&#34;&gt; &lt;/inline&gt; 
&lt;/scene&gt; 
&lt;/x3d&gt;  --&gt;
</description>
    </item>
    
    
    
    <item>
      <title>Hello USD - Part 11: Gotta make it easier to write file builders</title>
      <link>https://whynotestflight.com/excuses/hello-usd-part-11-gotta-make-it-easier-to-write-file-builders/</link>
      <pubDate>Mon, 17 Jul 2023 00:00:00 +0000</pubDate>
      
      <guid>https://whynotestflight.com/excuses/hello-usd-part-11-gotta-make-it-easier-to-write-file-builders/</guid>
      <description>&lt;p&gt;Right now all I&amp;rsquo;m asking of my little DSL is to place colored spheres at locations and my two FileBuilder types are both 100+ lines of code long, and contain gems like the following from the x3d builder:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;!&lt;/span&gt;shape.transformations.&lt;span style=&#34;color:#91d7e3&#34;&gt;isEmpty&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;for&lt;/span&gt; transform &lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt; shape.transformations {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            transformStart(transform:transform)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;!&lt;/span&gt;shape.transformations.&lt;span style=&#34;color:#91d7e3&#34;&gt;isEmpty&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;for&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;0.&lt;/span&gt;.&amp;lt;shape.transformations.&lt;span style=&#34;color:#91d7e3&#34;&gt;count&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            transformClose()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Where &lt;code&gt;transformClose()&lt;/code&gt; is just returns &lt;code&gt;&amp;lt;/transform&amp;gt;&lt;/code&gt;&amp;quot;&lt;/p&gt;
&lt;p&gt;Then more chunks like the below in the the .usda builder:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\t&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;}&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;}&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;I have to remember to close out sections and add the indents. Manually. For everything.&lt;/p&gt;
&lt;p&gt;What a troubleshooting nightmare.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;d much prefer to be able to write things like like:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;tag(name:&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;translate&amp;#34;&lt;/span&gt;, attributeDict:transDict) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//or&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Translate(x:&lt;span style=&#34;color:#f5a97f&#34;&gt;2&lt;/span&gt;, y:&lt;span style=&#34;color:#f5a97f&#34;&gt;3&lt;/span&gt;, z:&lt;span style=&#34;color:#f5a97f&#34;&gt;4&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Code like that would make my builders easier to update and potentially provide a nice tool for other people to potentially write their own.&lt;/p&gt;
&lt;p&gt;Code like this cannot be easily backed by any of the builtin &lt;a href=&#34;https://docs.swift.org/swift-book/documentation/the-swift-programming-language/collectiontypes/&#34;&gt;collections&lt;/a&gt;. Maybe I could have done something fancy with a &lt;code&gt;Deque&lt;/code&gt; from the &lt;a href=&#34;https://www.swift.org/blog/swift-collections/&#34;&gt;Collections Package&lt;/a&gt; &lt;a href=&#34;https://github.com/apple/swift-collections&#34;&gt;github&lt;/a&gt;?&lt;/p&gt;
&lt;p&gt;What I reached for instead is a &lt;a href=&#34;https://en.wikipedia.org/wiki/Tree_(data_structure)&#34;&gt;tree&lt;/a&gt;, which I plan to get cozy with for the 3D scene information anyway.&lt;/p&gt;
&lt;p&gt;I first implemented a tree in Swift for this past December&amp;rsquo;s &lt;a href=&#34;https://adventofcode.com/2022/day/13&#34;&gt;Advent of Code Day 13&lt;/a&gt; that looked like:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;enum&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;Message&lt;/span&gt;: ExpressibleByIntegerLiteral, 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;              ExpressibleByArrayLiteral, &lt;span style=&#34;color:#91d7e3&#34;&gt;Comparable&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;case&lt;/span&gt; value(&lt;span style=&#34;color:#91d7e3&#34;&gt;Int&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;indirect&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;case&lt;/span&gt; list([Message])
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;init&lt;/span&gt;(integerLiteral: &lt;span style=&#34;color:#91d7e3&#34;&gt;Int&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt; = .value(integerLiteral)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//for compliance with expressible by arrayliteral&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;init&lt;/span&gt;(arrayLiteral: &lt;span style=&#34;color:#f5a97f&#34;&gt;Self&lt;/span&gt;...) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt; = .list(arrayLiteral)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;init&lt;/span&gt;(from decoder: Decoder) &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;do&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;c&lt;/span&gt; = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; decoder.singleValueContainer()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt; = .value(&lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; c.decode(&lt;span style=&#34;color:#91d7e3&#34;&gt;Int&lt;/span&gt;.&lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        } &lt;span style=&#34;color:#c6a0f6&#34;&gt;catch&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt; = .list(&lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; [Message](from: decoder))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;lt;&lt;/span&gt; (lhs: &lt;span style=&#34;color:#f5a97f&#34;&gt;Self&lt;/span&gt;, rhs: &lt;span style=&#34;color:#f5a97f&#34;&gt;Self&lt;/span&gt;) -&amp;gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;Bool&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;switch&lt;/span&gt; (lhs, rhs) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;case&lt;/span&gt; (.value(&lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;l&lt;/span&gt;), .value(&lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;r&lt;/span&gt;)): &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; l &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;lt;&lt;/span&gt; r
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;case&lt;/span&gt; (.value(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt;), .list(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt;)): &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; .list([lhs]) &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;lt;&lt;/span&gt; rhs
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;case&lt;/span&gt; (.list(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt;), .value(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt;)): &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; lhs &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;lt;&lt;/span&gt; .list([rhs])
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;case&lt;/span&gt; (.list(&lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;l&lt;/span&gt;), .list(&lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;r&lt;/span&gt;)):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;for&lt;/span&gt; (le, re) &lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt; zip(l, r) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; le &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;lt;&lt;/span&gt; re { &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;true&lt;/span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; le &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;gt;&lt;/span&gt; re { &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;false&lt;/span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; l.&lt;span style=&#34;color:#91d7e3&#34;&gt;count&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;lt;&lt;/span&gt; r.&lt;span style=&#34;color:#91d7e3&#34;&gt;count&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;It uses an &lt;a href=&#34;https://docs.swift.org/swift-book/LanguageGuide/Enumerations.html&#34;&gt;enum&lt;/a&gt;, explicitly an &lt;a href=&#34;https://www.hackingwithswift.com/example-code/language/what-are-indirect-enums&#34;&gt;indirect case&lt;/a&gt;. &lt;a href=&#34;https://docs.swift.org/swift-book/documentation/the-swift-programming-language/enumerations/#Recursive-Enumerations&#34;&gt;More on Recursive Enums&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;For this task I don&amp;rsquo;t need a list, but a container.&lt;/p&gt;
&lt;p&gt;Note that &lt;code&gt;stringify&lt;/code&gt; recursively walks the tree.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;enum&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;StringNode&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;case&lt;/span&gt; content(&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;indirect&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;case&lt;/span&gt; container((&lt;span style=&#34;color:#c6a0f6&#34;&gt;prefix&lt;/span&gt;:&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;, content:StringNode, &lt;span style=&#34;color:#91d7e3&#34;&gt;suffix&lt;/span&gt;:&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;init&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; string:&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt; = .content(string)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;init&lt;/span&gt;(&lt;span style=&#34;color:#c6a0f6&#34;&gt;prefix&lt;/span&gt;:&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;, content:&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;, &lt;span style=&#34;color:#91d7e3&#34;&gt;suffix&lt;/span&gt;:&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt; = .container((&lt;span style=&#34;color:#c6a0f6&#34;&gt;prefix&lt;/span&gt;: &lt;span style=&#34;color:#c6a0f6&#34;&gt;prefix&lt;/span&gt;, content: .content(content), &lt;span style=&#34;color:#91d7e3&#34;&gt;suffix&lt;/span&gt;: &lt;span style=&#34;color:#91d7e3&#34;&gt;suffix&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;init&lt;/span&gt;(&lt;span style=&#34;color:#c6a0f6&#34;&gt;prefix&lt;/span&gt;:&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;, content:StringNode, &lt;span style=&#34;color:#91d7e3&#34;&gt;suffix&lt;/span&gt;:&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt; = .container((&lt;span style=&#34;color:#c6a0f6&#34;&gt;prefix&lt;/span&gt;: &lt;span style=&#34;color:#c6a0f6&#34;&gt;prefix&lt;/span&gt;, content: content, &lt;span style=&#34;color:#91d7e3&#34;&gt;suffix&lt;/span&gt;: &lt;span style=&#34;color:#91d7e3&#34;&gt;suffix&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;stringify&lt;/span&gt;(node:StringNode) -&amp;gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;switch&lt;/span&gt; node {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;case&lt;/span&gt; .content(&lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;s&lt;/span&gt;):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; s
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;case&lt;/span&gt; .container(&lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;tuple&lt;/span&gt;):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;prefix&lt;/span&gt; = tuple.&lt;span style=&#34;color:#c6a0f6&#34;&gt;prefix&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;suffix&lt;/span&gt; = tuple.&lt;span style=&#34;color:#91d7e3&#34;&gt;suffix&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;content&lt;/span&gt; = stringify(node: tuple.content)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;prefix&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;)\(&lt;/span&gt;content&lt;span style=&#34;color:#a6da95&#34;&gt;)\(&lt;/span&gt;&lt;span style=&#34;color:#91d7e3&#34;&gt;suffix&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;stringify&lt;/span&gt;(nodeSet:[StringNode]) -&amp;gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        nodeSet.&lt;span style=&#34;color:#91d7e3&#34;&gt;map&lt;/span&gt;({ &lt;span style=&#34;color:#f4dbd6&#34;&gt;$0&lt;/span&gt;.makeString() }).joined()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;makeString&lt;/span&gt;() -&amp;gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f5a97f&#34;&gt;Self&lt;/span&gt;.stringify(node: &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;message&lt;/span&gt;:StringNode = .content(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;I have a message&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;bracketedMessage&lt;/span&gt; = StringNode(&lt;span style=&#34;color:#c6a0f6&#34;&gt;prefix&lt;/span&gt;:&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&amp;lt;p&amp;gt;&amp;#34;&lt;/span&gt;, content: message, &lt;span style=&#34;color:#91d7e3&#34;&gt;suffix&lt;/span&gt;:&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&amp;lt;/p&amp;gt;&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;oneMoreDown&lt;/span&gt; = StringNode(&lt;span style=&#34;color:#c6a0f6&#34;&gt;prefix&lt;/span&gt;:&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&amp;lt;body&amp;gt;&amp;#34;&lt;/span&gt;, content: bracketedMessage, &lt;span style=&#34;color:#91d7e3&#34;&gt;suffix&lt;/span&gt;:&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&amp;lt;/body&amp;gt;&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(bracketedMessage.makeString())
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(oneMoreDown.makeString())
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The code above can be pasted into a playground and will result with the following printed to the console:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-html&#34; data-lang=&#34;html&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;p&lt;/span&gt;&amp;gt;I have a message&amp;lt;/&lt;span style=&#34;color:#c6a0f6&#34;&gt;p&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;body&lt;/span&gt;&amp;gt;&amp;lt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;p&lt;/span&gt;&amp;gt;I have a message&amp;lt;/&lt;span style=&#34;color:#c6a0f6&#34;&gt;p&lt;/span&gt;&amp;gt;&amp;lt;/&lt;span style=&#34;color:#c6a0f6&#34;&gt;body&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Great start, but those initializers will be tedious to write.&lt;/p&gt;
&lt;p&gt;Adding the following to the playground&amp;hellip;&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;@resultBuilder
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;enum&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;StringNodeBuilder&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;buildBlock&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; components: [StringNode]...) -&amp;gt; [StringNode] {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        buildArray(components)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;buildExpression&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; expression: StringNode) -&amp;gt; [StringNode] {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        [expression]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;buildArray&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; components: [[StringNode]]) -&amp;gt; [StringNode] {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; components.flatMap { &lt;span style=&#34;color:#f4dbd6&#34;&gt;$0&lt;/span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;buildExpression&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; expression: &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;) -&amp;gt; [StringNode] {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        [.content(expression)]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;buildExpression&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; components: &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;...) -&amp;gt; [StringNode] {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        components.compactMap { .content(&lt;span style=&#34;color:#f4dbd6&#34;&gt;$0&lt;/span&gt;) }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;buildExpression&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; components: [&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;]...) -&amp;gt; [StringNode] {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        components.flatMap { &lt;span style=&#34;color:#f4dbd6&#34;&gt;$0&lt;/span&gt; }.compactMap { .content(&lt;span style=&#34;color:#f4dbd6&#34;&gt;$0&lt;/span&gt;) }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;Document&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;content&lt;/span&gt;:[StringNode]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;init&lt;/span&gt;(@StringNodeBuilder content: () -&amp;gt; [StringNode]) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;.content = content()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;render&lt;/span&gt;() -&amp;gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        StringNode.stringify(nodeSet: content)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;document&lt;/span&gt; = Document {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Header&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    oneMoreDown
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Footer&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(document.render())
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&amp;hellip; writes &lt;code&gt;Header&amp;lt;body&amp;gt;&amp;lt;p&amp;gt;I have a message&amp;lt;/p&amp;gt;&amp;lt;/body&amp;gt;Footer&lt;/code&gt; to the output.&lt;/p&gt;
&lt;p&gt;This will be great for minified output situations, but will be hard for me to scan for errors.  While I would love to add a more extensible output formatter setup for now I just added the following to StringNode. Note that &lt;code&gt;indentStringify&lt;/code&gt;, like &lt;code&gt;stringify&lt;/code&gt; uses recursion.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;private&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;indentStringify&lt;/span&gt;(node: StringNode, level:&lt;span style=&#34;color:#91d7e3&#34;&gt;Int&lt;/span&gt; = &lt;span style=&#34;color:#f5a97f&#34;&gt;0&lt;/span&gt;) -&amp;gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;indent&lt;/span&gt; = Indent(&lt;span style=&#34;color:#91d7e3&#34;&gt;count&lt;/span&gt;: level, &lt;span style=&#34;color:#c6a0f6&#34;&gt;prefix&lt;/span&gt;: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;ind&lt;/span&gt; = indent.value
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;switch&lt;/span&gt; node {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;case&lt;/span&gt; .content(&lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;s&lt;/span&gt;):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;ind&lt;span style=&#34;color:#a6da95&#34;&gt;)\(&lt;/span&gt;s&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;case&lt;/span&gt; .container(&lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;tuple&lt;/span&gt;):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;prefix&lt;/span&gt; = tuple.&lt;span style=&#34;color:#c6a0f6&#34;&gt;prefix&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;suffix&lt;/span&gt; = tuple.&lt;span style=&#34;color:#91d7e3&#34;&gt;suffix&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;content&lt;/span&gt; = indentStringify(node: tuple.content, level: level &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;+&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;1&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;ind&lt;span style=&#34;color:#a6da95&#34;&gt;)\(&lt;/span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;prefix&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;)\(&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\n&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;)\(&lt;/span&gt;content&lt;span style=&#34;color:#a6da95&#34;&gt;)\(&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\n&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;)\(&lt;/span&gt;ind&lt;span style=&#34;color:#a6da95&#34;&gt;)\(&lt;/span&gt;&lt;span style=&#34;color:#91d7e3&#34;&gt;suffix&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;indentStringify&lt;/span&gt;(nodeSet:[StringNode],
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                                startLevel:&lt;span style=&#34;color:#91d7e3&#34;&gt;Int&lt;/span&gt; = &lt;span style=&#34;color:#f5a97f&#34;&gt;0&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                                separator:&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;=&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;) -&amp;gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        nodeSet.&lt;span style=&#34;color:#91d7e3&#34;&gt;map&lt;/span&gt;({
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#f4dbd6&#34;&gt;$0&lt;/span&gt;.indentedString(startLevel: startLevel)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }).joined(separator: separator)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;indentedString&lt;/span&gt;(startLevel:&lt;span style=&#34;color:#91d7e3&#34;&gt;Int&lt;/span&gt; = &lt;span style=&#34;color:#f5a97f&#34;&gt;0&lt;/span&gt;) -&amp;gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f5a97f&#34;&gt;Self&lt;/span&gt;.indentStringify(node: &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;, level: startLevel)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The following helper struct to the top of the file:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;Indent&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;count&lt;/span&gt;:&lt;span style=&#34;color:#91d7e3&#34;&gt;Int&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;indentString&lt;/span&gt;:&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;prefix&lt;/span&gt;:&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;init&lt;/span&gt;(&lt;span style=&#34;color:#91d7e3&#34;&gt;count&lt;/span&gt;:&lt;span style=&#34;color:#91d7e3&#34;&gt;Int&lt;/span&gt;, indentString:&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt; = &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\t&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#c6a0f6&#34;&gt;prefix&lt;/span&gt;:&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;=&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;.&lt;span style=&#34;color:#91d7e3&#34;&gt;count&lt;/span&gt; = &lt;span style=&#34;color:#91d7e3&#34;&gt;count&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;.indentString = indentString
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;.&lt;span style=&#34;color:#c6a0f6&#34;&gt;prefix&lt;/span&gt; = &lt;span style=&#34;color:#c6a0f6&#34;&gt;prefix&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;value&lt;/span&gt;:&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;tmp&lt;/span&gt; = &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;for&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;0.&lt;/span&gt;.&amp;lt;&lt;span style=&#34;color:#91d7e3&#34;&gt;count&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            tmp.append(indentString)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;prefix&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;)\(&lt;/span&gt;tmp&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And update the &lt;code&gt;render&lt;/code&gt; function in &lt;code&gt;Document&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;render&lt;/span&gt;() -&amp;gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; StringNode.indentStringify(nodeSet: content, separator:&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\n&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;To get:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-html&#34; data-lang=&#34;html&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Header
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;body&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	&amp;lt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;p&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;		I have a message
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	&amp;lt;/&lt;span style=&#34;color:#c6a0f6&#34;&gt;p&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;/&lt;span style=&#34;color:#c6a0f6&#34;&gt;body&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Footer
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;To make a custom encloser we can add a protocol &lt;code&gt;Nodeable&lt;/code&gt;&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;FunTag&lt;/span&gt;:Nodeable {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;prefix&lt;/span&gt;:&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt; = &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&amp;lt;FUNTAG&amp;gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;suffix&lt;/span&gt;:&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt; = &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&amp;lt;/FUNTAG&amp;gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;content&lt;/span&gt;:StringNode
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;asStringNode&lt;/span&gt;: StringNode {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        .container((&lt;span style=&#34;color:#c6a0f6&#34;&gt;prefix&lt;/span&gt;: &lt;span style=&#34;color:#c6a0f6&#34;&gt;prefix&lt;/span&gt;, content: content, &lt;span style=&#34;color:#91d7e3&#34;&gt;suffix&lt;/span&gt;: &lt;span style=&#34;color:#91d7e3&#34;&gt;suffix&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;extension&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;FunTag&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;init&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; content:()-&amp;gt;Nodeable) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;.content = content().asStringNode
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;With the following additions to the result builder:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;buildExpression&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; expression: Nodeable) -&amp;gt; [StringNode] {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        [expression.asStringNode]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;buildExpression&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; components: Nodeable...) -&amp;gt; [StringNode] {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        components.compactMap { &lt;span style=&#34;color:#f4dbd6&#34;&gt;$0&lt;/span&gt;.asStringNode }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;buildExpression&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; components: [Nodeable]...) -&amp;gt; [StringNode] {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        components.flatMap { &lt;span style=&#34;color:#f4dbd6&#34;&gt;$0&lt;/span&gt; }.compactMap { &lt;span style=&#34;color:#f4dbd6&#34;&gt;$0&lt;/span&gt;.asStringNode }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;If I want FunTag to be able to take Strings, I have to comment out the  String based expression blocks in the builder and conform String to Nodeable. Otherwise the builder gets confused if it should use the String builder or the Nodeable builder.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;extension&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;String&lt;/span&gt;:Nodeable {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;asStringNode&lt;/span&gt;: StringNode {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        .content(&lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Update the Document:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;document&lt;/span&gt; = Document {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Header&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    oneMoreDown
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    FunTag(content: bracketedMessage)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    FunTag { &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Test&amp;#34;&lt;/span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Footer&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-html&#34; data-lang=&#34;html&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Header
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;body&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	&amp;lt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;p&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;		I have a message
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	&amp;lt;/&lt;span style=&#34;color:#c6a0f6&#34;&gt;p&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;/&lt;span style=&#34;color:#c6a0f6&#34;&gt;body&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;FUNTAG&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	&amp;lt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;p&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;		I have a message
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	&amp;lt;/&lt;span style=&#34;color:#c6a0f6&#34;&gt;p&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;/&lt;span style=&#34;color:#c6a0f6&#34;&gt;FUNTAG&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;FUNTAG&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	Test
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;/&lt;span style=&#34;color:#c6a0f6&#34;&gt;FUNTAG&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Footer
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The one thing I can&amp;rsquo;t do is add more than one item to the FunTag as siblings. If I tried to run the following&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;document&lt;/span&gt; = Document {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Header&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    oneMoreDown
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    FunTag(content: bracketedMessage)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    FunTag {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Test&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        bracketedMessage
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Footer&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;It gets the error message &lt;code&gt;Missing return in closure expected to return &#39;any Nodeable&#39;&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Changing the initializer of &lt;code&gt;FunTag&lt;/code&gt; to match what Document uses&amp;hellip;&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;    init(@StringNodeBuilder content: () -&amp;gt; [StringNode]) {
        self.content = content()
    }
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&amp;hellip; nets the response &lt;code&gt;Cannot assign value of type &#39;[StringNode]&#39; to type &#39;StringNode&#39;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;There needs to be a StringNode type that understands siblings that can take a &lt;code&gt;[StringNode]&lt;/code&gt; and make that un-nested list into a &lt;code&gt;StringNode&lt;/code&gt; itself.&lt;/p&gt;
&lt;p&gt;Going back to add that list feature after all.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;enum&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;StringNode&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;case&lt;/span&gt; content(&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;indirect&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;case&lt;/span&gt; container((&lt;span style=&#34;color:#c6a0f6&#34;&gt;prefix&lt;/span&gt;:&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;, content:StringNode, &lt;span style=&#34;color:#91d7e3&#34;&gt;suffix&lt;/span&gt;:&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;indirect&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;case&lt;/span&gt; list([StringNode])
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;///...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;private&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;stringify&lt;/span&gt;(node:StringNode) -&amp;gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;switch&lt;/span&gt; node {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;///...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;case&lt;/span&gt; .list(&lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;nodeArray&lt;/span&gt;):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;Self&lt;/span&gt;.stringify(nodeSet: nodeArray)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;private&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;indentStringify&lt;/span&gt;(node: StringNode, level:&lt;span style=&#34;color:#91d7e3&#34;&gt;Int&lt;/span&gt; = &lt;span style=&#34;color:#f5a97f&#34;&gt;0&lt;/span&gt;) -&amp;gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;///...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;switch&lt;/span&gt; node {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;///...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;case&lt;/span&gt; .list(&lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;nodeArray&lt;/span&gt;):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; indentStringify(nodeSet:nodeArray, startLevel:level, separator:&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\n&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Add a &lt;code&gt;RenderStyle&lt;/code&gt; to let me troubleshoot both&amp;hellip;&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;Document&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;enum&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;RenderStyle&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;case&lt;/span&gt; minimal
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;case&lt;/span&gt; indented
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;render&lt;/span&gt;(style: RenderStyle = .indented) -&amp;gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;switch&lt;/span&gt; style {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;case&lt;/span&gt; .indented:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; StringNode.indentStringify(nodeSet: content)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;case&lt;/span&gt; .minimal:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; StringNode.stringify(nodeSet: content)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(document.render())
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(document.render(style: .minimal))
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Success!&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-html&#34; data-lang=&#34;html&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Header
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;body&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	&amp;lt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;p&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;		I have a message
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	&amp;lt;/&lt;span style=&#34;color:#c6a0f6&#34;&gt;p&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;/&lt;span style=&#34;color:#c6a0f6&#34;&gt;body&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;FUNTAG&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	&amp;lt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;p&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;		I have a message
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	&amp;lt;/&lt;span style=&#34;color:#c6a0f6&#34;&gt;p&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;/&lt;span style=&#34;color:#c6a0f6&#34;&gt;FUNTAG&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;FUNTAG&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	Test
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	&amp;lt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;p&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;		I have a message
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	&amp;lt;/&lt;span style=&#34;color:#c6a0f6&#34;&gt;p&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;/&lt;span style=&#34;color:#c6a0f6&#34;&gt;FUNTAG&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Footer
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;One last thing. Now we can make lots of helpers. As long as they conform to Nodeable they will work in the builder.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;AttributedTag&lt;/span&gt;:Nodeable {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;name&lt;/span&gt;:&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;id&lt;/span&gt;:&lt;span style=&#34;color:#91d7e3&#34;&gt;Int&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;prefix&lt;/span&gt;: &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt; { &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&amp;lt;&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;name&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt; attribute=&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;id&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;gt;&amp;#34;&lt;/span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;suffix&lt;/span&gt;: &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt; { &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&amp;lt;/&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;name&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;gt;&amp;#34;&lt;/span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;content&lt;/span&gt;: StringNode
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;init&lt;/span&gt;(name:&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;, attribute:&lt;span style=&#34;color:#91d7e3&#34;&gt;Int&lt;/span&gt;, @StringNodeBuilder content: () -&amp;gt; [StringNode]) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;.name = name
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;.id = attribute
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;.content = .list(content())
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;asStringNode&lt;/span&gt;: StringNode {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        .container((&lt;span style=&#34;color:#c6a0f6&#34;&gt;prefix&lt;/span&gt;: &lt;span style=&#34;color:#c6a0f6&#34;&gt;prefix&lt;/span&gt;, content: content, &lt;span style=&#34;color:#91d7e3&#34;&gt;suffix&lt;/span&gt;: &lt;span style=&#34;color:#91d7e3&#34;&gt;suffix&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;Repeater&lt;/span&gt;:Nodeable {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;count&lt;/span&gt;:&lt;span style=&#34;color:#91d7e3&#34;&gt;Int&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;content&lt;/span&gt;: StringNode
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;init&lt;/span&gt;(&lt;span style=&#34;color:#91d7e3&#34;&gt;count&lt;/span&gt;:&lt;span style=&#34;color:#91d7e3&#34;&gt;Int&lt;/span&gt;, @StringNodeBuilder content: () -&amp;gt; [StringNode]) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;.&lt;span style=&#34;color:#91d7e3&#34;&gt;count&lt;/span&gt; = &lt;span style=&#34;color:#91d7e3&#34;&gt;count&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;.content = .list(content())
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;asStringNode&lt;/span&gt;: StringNode {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;tmp&lt;/span&gt;:[StringNode] = []
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;for&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;0.&lt;/span&gt;.&amp;lt;&lt;span style=&#34;color:#91d7e3&#34;&gt;count&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            tmp.append(content)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; .list(tmp)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;document&lt;/span&gt; = Document {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Header&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    oneMoreDown
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    FunTag(content: bracketedMessage)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    AttributedTag(name: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;MEANING&amp;#34;&lt;/span&gt;, attribute: &lt;span style=&#34;color:#f5a97f&#34;&gt;42&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        FunTag {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Test&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            bracketedMessage
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    Repeater(&lt;span style=&#34;color:#91d7e3&#34;&gt;count&lt;/span&gt;: &lt;span style=&#34;color:#f5a97f&#34;&gt;3&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Hi!&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Footer&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Again Success!&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-html&#34; data-lang=&#34;html&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Header
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;body&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	&amp;lt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;p&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;		I have a message
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	&amp;lt;/&lt;span style=&#34;color:#c6a0f6&#34;&gt;p&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;/&lt;span style=&#34;color:#c6a0f6&#34;&gt;body&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;FUNTAG&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	&amp;lt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;p&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;		I have a message
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	&amp;lt;/&lt;span style=&#34;color:#c6a0f6&#34;&gt;p&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;/&lt;span style=&#34;color:#c6a0f6&#34;&gt;FUNTAG&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;MEANING&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;attribute&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;42&amp;#34;&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	&amp;lt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;FUNTAG&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;		Test
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;		&amp;lt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;p&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;			I have a message
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;		&amp;lt;/&lt;span style=&#34;color:#c6a0f6&#34;&gt;p&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	&amp;lt;/&lt;span style=&#34;color:#c6a0f6&#34;&gt;FUNTAG&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;/&lt;span style=&#34;color:#c6a0f6&#34;&gt;MEANING&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Hi!
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Hi!
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Hi!
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Footer
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This all puts me in great shape to refactor my two file builders next time.&lt;/p&gt;
&lt;p&gt;Complete code:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;with_list_bonus_tags.txt&#34;&gt;linked file&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://gist.github.com/carlynorama/088fd2bb77cb9d4fabb0c55e50f780b5&#34;&gt;gist&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</description>
    </item>
    
    
    
    <item>
      <title>Hunh... my code lines are really long</title>
      <link>https://whynotestflight.com/excuses/hunh...-my-code-lines-are-really-long/</link>
      <pubDate>Sat, 15 Jul 2023 00:00:00 +0000</pubDate>
      
      <guid>https://whynotestflight.com/excuses/hunh...-my-code-lines-are-really-long/</guid>
      <description>&lt;p&gt;In previous posts the code contains some really long lines, making them hard to read.&lt;/p&gt;
&lt;h1 id=&#34;line-wrap--line-numbers&#34;&gt;Line Wrap &amp;amp; Line Numbers&lt;/h1&gt;
&lt;p&gt;First I thought about adding line numbers and wrapping.&lt;/p&gt;
&lt;p&gt;In hugo.toml added some &lt;a href=&#34;https://gohugo.io/getting-started/configuration-markup/#highlight&#34;&gt;markup updates&lt;/a&gt;&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-toml&#34; data-lang=&#34;toml&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;[markup]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  [markup.highlight]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    lineNos = &lt;span style=&#34;color:#f5a97f&#34;&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;I&amp;rsquo;m using the &lt;a href=&#34;https://themes.gohugo.io/themes/etch/&#34;&gt;etch theme&lt;/a&gt; so I copied &lt;code&gt;themes/etch/assets/main.css&lt;/code&gt; to &lt;code&gt;/asset/css/main.css&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;In main.css code blocks have the following css associated with them&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-css&#34; data-lang=&#34;css&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;main&lt;/span&gt;#&lt;span style=&#34;color:#f5a97f&#34;&gt;content&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;pre&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;display&lt;/span&gt;: &lt;span style=&#34;color:#f5a97f&#34;&gt;block&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;overflow-x&lt;/span&gt;: &lt;span style=&#34;color:#f5a97f&#34;&gt;auto&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;font-size&lt;/span&gt;: &lt;span style=&#34;color:#f5a97f&#34;&gt;14&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;px&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;font-size&lt;/span&gt;: &lt;span style=&#34;color:#f5a97f&#34;&gt;1.4&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;rem&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;white-space&lt;/span&gt;: &lt;span style=&#34;color:#f5a97f&#34;&gt;pre&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;margin&lt;/span&gt;: &lt;span style=&#34;color:#f5a97f&#34;&gt;20&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;px&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;0&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;padding&lt;/span&gt;: &lt;span style=&#34;color:#f5a97f&#34;&gt;1.5&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;rem&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;1.5&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;rem&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;line-height&lt;/span&gt;: &lt;span style=&#34;color:#f5a97f&#34;&gt;1.4&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Following directions found in the &lt;a href=&#34;https://discourse.gohugo.io/t/set-width-when-using-syntax-highlighting-and-code-fences/26544&#34;&gt;hugo forums&lt;/a&gt;, I tried adding&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-css&#34; data-lang=&#34;css&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;main&lt;/span&gt;#&lt;span style=&#34;color:#f5a97f&#34;&gt;content&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;pre&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;/*overflow-x: visible;*/&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;white-space&lt;/span&gt;: &lt;span style=&#34;color:#f5a97f&#34;&gt;pre-wrap&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;word-break&lt;/span&gt;: &lt;span style=&#34;color:#f5a97f&#34;&gt;break-word&lt;/span&gt;; 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;to the bottom of the file. This css made the code wrap, but it screwed up the line numbers making them wrap to two lines too, which screwed up the line heights&amp;hellip;&lt;/p&gt;
&lt;p&gt;I didn&amp;rsquo;t feel strongly enough about that solution to go deep into the theme&amp;rsquo;s style sheets so I turned off all of those changes and let everything flow wider, updating the body css in my copy of min770.css to:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-css&#34; data-lang=&#34;css&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;body&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;max-width&lt;/span&gt;: &lt;span style=&#34;color:#f5a97f&#34;&gt;70&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;%&lt;/span&gt;; &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;/*from 600px*/&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;line-height&lt;/span&gt;: &lt;span style=&#34;color:#f5a97f&#34;&gt;1.5&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;I didn&amp;rsquo;t love this solution because narrower columns &lt;a href=&#34;https://www.paulolyslager.com/optimal-text-layout-line-length/&#34;&gt;make for easier reading&lt;/a&gt;, &lt;a href=&#34;https://graphicdesign.stackexchange.com/questions/13724/recommended-column-width-for-text-reading-digital-vs-printed&#34;&gt;in general&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;better-guides-for-better-code&#34;&gt;Better guides for better code&lt;/h2&gt;
&lt;p&gt;The best solution? Write narrower code. Since I&amp;rsquo;m using VSCode I can &lt;a href=&#34;https://dev.to/brad_beggs/vs-code-vertical-rulers-for-prettier-code-3gp3&#34;&gt;turn on guide rulers&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Add the following json to settings.json (cmd+shit+p, type settings)&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-json&#34; data-lang=&#34;json&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;editor.rulers&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;:&lt;/span&gt; [
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f5a97f&#34;&gt;80&lt;/span&gt;,  &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//first ruler, no color specified, low key guide
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;    {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;&amp;#34;column&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#f5a97f&#34;&gt;100&lt;/span&gt;,       &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// second ruler
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;&amp;#34;color&amp;#34;&lt;/span&gt;:  &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;#9f0af5&amp;#34;&lt;/span&gt;  &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// wrap it up...
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;    },
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;&amp;#34;column&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#f5a97f&#34;&gt;120&lt;/span&gt;,      &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// third ruler
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;&amp;#34;color&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;#ff9900&amp;#34;&lt;/span&gt;  &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// better have a good reason! 
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;    },
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;]&lt;span style=&#34;color:#ed8796&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now I&amp;rsquo;ll have a visual maker when I&amp;rsquo;m going too wide.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ve also decided to disallow wrapping in Python files at all. We&amp;rsquo;ll see how long that lasts.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-json&#34; data-lang=&#34;json&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;[python]&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;:&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;&amp;#34;editor.formatOnType&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#f5a97f&#34;&gt;true&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;&amp;#34;editor.wordWrap&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;off&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;span style=&#34;color:#ed8796&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;re-narrowing-the-body&#34;&gt;Re-narrowing the body&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;/asset/css/min770.css&lt;/code&gt; now reads&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-css&#34; data-lang=&#34;css&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;body&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;max-width&lt;/span&gt;: &lt;span style=&#34;color:#f5a97f&#34;&gt;70&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;rem&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;line-height&lt;/span&gt;: &lt;span style=&#34;color:#f5a97f&#34;&gt;1.5&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The unit &lt;code&gt;em&lt;/code&gt; comes from typography and stands for &amp;ldquo;the width of the letter M&amp;rdquo;. &lt;code&gt;rem&lt;/code&gt; stands for &amp;ldquo;root em&amp;rdquo;, which avoids the compounding effects of &lt;code&gt;em&lt;/code&gt;, which I was seeing when I tried that first. This new setting limits my content to 50 characters of the base font wide.&lt;/p&gt;
&lt;p&gt;The theme&amp;rsquo;s root font had an unexpected root font value of &lt;code&gt;font-size: 62.5%;&lt;/code&gt;, so that &amp;ldquo;70&amp;rdquo; actually gives us ~112 &amp;ldquo;M&amp;quot;s of width.&lt;/p&gt;
&lt;p&gt;But there could be much more I could do:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://www.smashingmagazine.com/2020/07/css-techniques-legibility/&#34;&gt;https://www.smashingmagazine.com/2020/07/css-techniques-legibility/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://www.smashingmagazine.com/printed-books/smashing-book-5/&#34;&gt;https://www.smashingmagazine.com/printed-books/smashing-book-5/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://www.w3.org/WAI/RD/2012/text-customization/r14&#34;&gt;https://www.w3.org/WAI/RD/2012/text-customization/r14&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://accessibility.huit.harvard.edu/10-essentials&#34;&gt;https://accessibility.huit.harvard.edu/10-essentials&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;line-numbers-back-on&#34;&gt;Line Numbers Back On&lt;/h2&gt;
&lt;p&gt;I decided I missed the line numbers, which makes 70rem too small for code blocks. Added the below to &lt;code&gt;main.css&lt;/code&gt;.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-css&#34; data-lang=&#34;css&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;div&lt;/span&gt;.&lt;span style=&#34;color:#eed49f&#34;&gt;highlight&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;min-width&lt;/span&gt;: &lt;span style=&#34;color:#f5a97f&#34;&gt;80&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;rem&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The general structure of the line numbered code blocks for reference (a one row 2 column table):&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-html&#34; data-lang=&#34;html&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;div&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;class&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;highlight&amp;#34;&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &amp;lt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;div&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;class&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;chroma&amp;#34;&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    &amp;lt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;table&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;class&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;lntable&amp;#34;&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                        &amp;lt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;tr&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                            &amp;lt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;td&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;class&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;lntd&amp;#34;&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                                &amp;lt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;pre&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;tabindex&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;0&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;class&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;chroma&amp;#34;&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                                    &amp;lt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;code&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                                    &amp;lt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;span&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;class&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;lnt&amp;#34;&lt;/span&gt;&amp;gt; 1&amp;lt;/&lt;span style=&#34;color:#c6a0f6&#34;&gt;span&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                                    &amp;lt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;span&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;class&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;lnt&amp;#34;&lt;/span&gt;&amp;gt; 2&amp;lt;/&lt;span style=&#34;color:#c6a0f6&#34;&gt;span&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                                    ...
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                                    &amp;lt;/&lt;span style=&#34;color:#c6a0f6&#34;&gt;code&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                                &amp;lt;/&lt;span style=&#34;color:#c6a0f6&#34;&gt;pre&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                            &amp;lt;/&lt;span style=&#34;color:#c6a0f6&#34;&gt;td&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                            &amp;lt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;td&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;class&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;lntd&amp;#34;&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                                &amp;lt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;pre&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;class&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;chroma&amp;#34;&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                                    &amp;lt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;code&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;class&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;language-$LANG&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;data-lang&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;$LANG&amp;#34;&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                                    ... more formatting spans and the code
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                                    &amp;lt;/&lt;span style=&#34;color:#c6a0f6&#34;&gt;code&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                                &amp;lt;/&lt;span style=&#34;color:#c6a0f6&#34;&gt;pre&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                            &amp;lt;/&lt;span style=&#34;color:#c6a0f6&#34;&gt;td&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;/&lt;span style=&#34;color:#c6a0f6&#34;&gt;tr&lt;/span&gt;&amp;gt;&amp;lt;/&lt;span style=&#34;color:#c6a0f6&#34;&gt;table&lt;/span&gt;&amp;gt;&amp;lt;/&lt;span style=&#34;color:#c6a0f6&#34;&gt;div&lt;/span&gt;&amp;gt;&amp;lt;/&lt;span style=&#34;color:#c6a0f6&#34;&gt;div&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;safarichrome-on-device-only-error&#34;&gt;Safari/Chrome on Device Only Error&lt;/h2&gt;
&lt;p&gt;I had never looked at this site on a mobile device before but the code block CSS was behaving VERY strangely on two different iPhones. The sizes of the fonts were very inconsistent from code block to code block with no perceptible pattern.  Not which language they held, not number of lines, not line length. I rolled back the changes I&amp;rsquo;d made and it didn&amp;rsquo;t fix it. I tried removing &lt;code&gt;pygmentsUseClasses = true&lt;/code&gt; from the hugo.toml and it changed in that now the font sizes on mobile devices were inconsistent between lines within the code block.&lt;/p&gt;
&lt;p&gt;The bug was not reproducible in &amp;ldquo;responsive mode&amp;rdquo; on either Safari or FireFox&lt;/p&gt;
&lt;p&gt;Safari version 16.5.2&lt;/p&gt;
&lt;h3 id=&#34;enable-safari-developer-tools-for-on-device-browser&#34;&gt;Enable Safari Developer Tools for On Device Browser&lt;/h3&gt;
&lt;p&gt;On phone: Settings &amp;gt; Safari &amp;gt; Advanced (at bottom) &amp;gt; Web Inspector&lt;/p&gt;
&lt;p&gt;Plug phone into computer via cable (Agree to Trust)&lt;/p&gt;
&lt;p&gt;In Safari choose the device from the top of the Develop menu, and sub-select the open web page you&amp;rsquo;d like to inspect.&lt;/p&gt;
&lt;h3 id=&#34;the-fix&#34;&gt;The Fix&lt;/h3&gt;
&lt;p&gt;The variable font size problem appears to have been fixed by adding classes back in, not through an explicit call to pygments, but updating the &lt;code&gt;[markup]&lt;/code&gt; block as the newest versions of Hugo documentation recommend.&lt;/p&gt;
&lt;p&gt;The class based version of the css and this theme works terribly with line numbers so those are off again.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;m still flummoxed by why this happened on actual mobile devices only, not in different browsers dev mode.&lt;/p&gt;
&lt;p&gt;hugo.toml went from&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-toml&#34; data-lang=&#34;toml&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;theme = &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;etch&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;enableInlineShortcodes = &lt;span style=&#34;color:#f5a97f&#34;&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;pygmentsCodeFences = &lt;span style=&#34;color:#f5a97f&#34;&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;pygmentsUseClasses = &lt;span style=&#34;color:#f5a97f&#34;&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;[markup]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  [markup.highlight]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    lineNos = &lt;span style=&#34;color:#f5a97f&#34;&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;to&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-toml&#34; data-lang=&#34;toml&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;theme = &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;etch&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;enableInlineShortcodes = &lt;span style=&#34;color:#f5a97f&#34;&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;[markup]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  [markup.highlight]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    lineNos = &lt;span style=&#34;color:#f5a97f&#34;&gt;false&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    codeFences = &lt;span style=&#34;color:#f5a97f&#34;&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    noClasses = &lt;span style=&#34;color:#f5a97f&#34;&gt;false&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;/asset/css/min770.css&lt;/code&gt; again has the following changes compared to theme CSS.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-css&#34; data-lang=&#34;css&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;body&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;max-width&lt;/span&gt;: &lt;span style=&#34;color:#f5a97f&#34;&gt;75&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;rem&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;line-height&lt;/span&gt;: &lt;span style=&#34;color:#f5a97f&#34;&gt;1.5&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;div&lt;/span&gt;.&lt;span style=&#34;color:#eed49f&#34;&gt;highlight&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;min-width&lt;/span&gt;: &lt;span style=&#34;color:#f5a97f&#34;&gt;85&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;rem&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Interesting links found along the way:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://discourse.gohugo.io/t/change-highlight-wrapper-class/26169&#34;&gt;https://discourse.gohugo.io/t/change-highlight-wrapper-class/26169&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://stackoverflow.com/questions/58089572/hugo-syntax-highlighting-not-changing&#34;&gt;https://stackoverflow.com/questions/58089572/hugo-syntax-highlighting-not-changing&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;My Problem? And yet labeled as not a &amp;ldquo;Hugo&amp;rdquo; problem. &lt;a href=&#34;https://discourse.gohugo.io/t/code-syntax-highlighting-problems-on-mobile/34247&#34;&gt;https://discourse.gohugo.io/t/code-syntax-highlighting-problems-on-mobile/34247&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://gohugo.io/getting-started/configuration-markup/#highlight&#34;&gt;https://gohugo.io/getting-started/configuration-markup/#highlight&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Discussion of line number css &lt;a href=&#34;https://discourse.gohugo.io/t/height-mismatch-of-highlighted-line-number-in-syntax-highlighting/42304/18&#34;&gt;https://discourse.gohugo.io/t/height-mismatch-of-highlighted-line-number-in-syntax-highlighting/42304/18&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</description>
    </item>
    
    
    
    <item>
      <title>Hello USD - Part 10: Reading Day</title>
      <link>https://whynotestflight.com/excuses/hello-usd-part-10-reading-day/</link>
      <pubDate>Fri, 14 Jul 2023 00:00:00 +0000</pubDate>
      
      <guid>https://whynotestflight.com/excuses/hello-usd-part-10-reading-day/</guid>
      <description>&lt;p&gt;What I thought was going to happen yesterday:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Make a FileBuilder protocol in SketchPad&lt;/li&gt;
&lt;li&gt;Refine StringBuilder to help make producing FileBuilders easier&lt;/li&gt;
&lt;li&gt;Write up a compare contrast between X3D and USD&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;What actually happened:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A reading day.&lt;/li&gt;
&lt;li&gt;Updated &lt;a href=&#34;https://github.com/carlynorama/USDHelloWorld&#34;&gt;USDHelloWorld/README.md&lt;/a&gt; to have the &amp;ldquo;top picks&amp;rdquo; section&lt;/li&gt;
&lt;li&gt;Updated &lt;a href=&#34;https://github.com/carlynorama/USDHelloWorld/blob/main/SETUP.md&#34;&gt;USDHelloWorld/SETUP.md&lt;/a&gt; to offer the easy pip install of python lib&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If I&amp;rsquo;m going to write &lt;a href=&#34;https://whynotestflight.com/excuses/hello-usd-part-9-parlez-vous-multiball-dsl-starts-here/&#34;&gt;a DSL&lt;/a&gt; that echos the philosophy of USD, I need to better understand the philosophy of USD. So I started looking for resources that provided overviews.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Finding tutorials on specific software tools that implement USD: very easy.&lt;/li&gt;
&lt;li&gt;Finding lectures / materials on the motivation and architecture: much harder.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I did end up finding a bunch of new references using search terms like &amp;ldquo;USD philosophy&amp;rdquo;, etc.  Also helpful, the &lt;a href=&#34;https://wiki.aswf.io/display/WGUSD/Learning+Content&#34;&gt;ASWF wiki&lt;/a&gt; references the &amp;ldquo;Book of USD&amp;rdquo; which ended up being one of my top picks. I wanted &amp;ldquo;USD solves these problems&amp;rdquo; kind of videos/articles, not &amp;ldquo;Use our tool to make a thing&amp;rdquo; info.&lt;/p&gt;
&lt;h2 id=&#34;top-picks&#34;&gt;Top Picks&lt;/h2&gt;
&lt;h3 id=&#34;brief-overview---4-min-video&#34;&gt;Brief Overview - 4 min Video&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Luk, Aaron. “Universal Scene Description (OpenUSD): 4 Superpowers to Get You Started,” Video (4:11). YouTube NVIDIA Developer Channel: &lt;a href=&#34;https://www.youtube.com/watch?v=1RnTSZK9SwM&#34;&gt;https://www.youtube.com/watch?v=1RnTSZK9SwM&lt;/a&gt;. Accessed: 2023 07 13.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Brief overview of what makes USD special by one of the folks who was there at the beginning.&lt;/p&gt;
&lt;h3 id=&#34;in-depth-hello-world---29-min-video&#34;&gt;In Depth Hello World - 29 min Video&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Van Gelder, Dirk, &amp;ldquo;Introduction to USD,&amp;rdquo; Video (26:36). NVidia-On-Demand, GTC Digital (April 2021): &lt;a href=&#34;https://www.nvidia.com/en-us/on-demand/session/gtcspring21-s33132/?playlistId=playList-911c5614-4b7f-4668-b9eb-37f627ac8d17&#34;&gt;https://www.nvidia.com/en-us/on-demand/session/gtcspring21-s33132/?playlistId=playList-911c5614-4b7f-4668-b9eb-37f627ac8d17&lt;/a&gt;. Accessed: 2023 07 13.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Does include 101 how to information, but also explains why USD does things that way.&lt;/p&gt;
&lt;h3 id=&#34;longer-overview---39-min-video&#34;&gt;Longer Overview - 39 min Video&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Luk, Aaron. &amp;ldquo;An Overview of Universal Scene Description (USD) for Building Virtual Worlds,&amp;rdquo; Video (39:36 minutes).  NVidia-On-Demand, GTC Digital Spring (March 2023). &lt;a href=&#34;https://www.nvidia.com/en-us/on-demand/session/gtcspring23-s52054/&#34;&gt;https://www.nvidia.com/en-us/on-demand/session/gtcspring23-s52054/&lt;/a&gt; Accessed: 2023 07 13.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Has many &amp;ldquo;where to find more info&amp;rdquo; resources at the end.&lt;/p&gt;
&lt;h3 id=&#34;two-companions&#34;&gt;Two Companions&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Various Authors. Book of USD: Getting Started With Universal Scene Description. &lt;a href=&#34;https://remedy-entertainment.github.io/USDBook/&#34;&gt;https://remedy-entertainment.github.io/USDBook/&lt;/a&gt; Accessed: 2023 07 13, &lt;a href=&#34;https://github.com/Remedy-Entertainment/USDBook/&#34;&gt;https://github.com/Remedy-Entertainment/USDBook/&lt;/a&gt; Accessed: 2023 07 14.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Various Authors. &amp;ldquo;USD Terms and Concepts.&amp;rdquo; Universal Scene Description. &lt;a href=&#34;https://openusd.org/release/glossary.html&#34;&gt;https://openusd.org/release/glossary.html&lt;/a&gt; Accessed: 2023 07 13, &lt;a href=&#34;https://github.com/PixarAnimationStudios/OpenUSD/tree/release/docs&#34;&gt;https://github.com/PixarAnimationStudios/OpenUSD/tree/release/docs&lt;/a&gt; Accessed: 2023 07 13.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The Glossary on the official documentation site holds a ton of in depth information, but it&amp;rsquo;s in alphabetical order, so it&amp;rsquo;s hard to read in a way that presents a cohesive narrative.&lt;/p&gt;
&lt;p&gt;The Book of USD resource provides simpler definitions in a useful order as an entry point to learn more. Very helpful. Also loved the ton of screen shots from &lt;code&gt;usdview&lt;/code&gt;. Bummed that like many resources it didn&amp;rsquo;t have much in terms of USDA file outputs, but that&amp;rsquo;s a me problem.&lt;/p&gt;
&lt;p&gt;The authors of the Book of USD recommend that one cross references what they&amp;rsquo;ve written with the official docs, so I am listing them as companions.&lt;/p&gt;
&lt;h3 id=&#34;biggest-omg&#34;&gt;Biggest OMG&lt;/h3&gt;
&lt;p&gt;&lt;a href=&#34;https://developer.nvidia.com/isaac-sim&#34;&gt;https://developer.nvidia.com/isaac-sim&lt;/a&gt; No spoilers.&lt;/p&gt;
&lt;h3 id=&#34;spec-related-list&#34;&gt;Spec related list&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Proposed Spec for USDA files discussion: &lt;a href=&#34;https://github.com/PixarAnimationStudios/OpenUSD/pull/2126&#34;&gt;https://github.com/PixarAnimationStudios/OpenUSD/pull/2126&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Proposed Spec for USDC files discussion: &lt;a href=&#34;https://github.com/PixarAnimationStudios/OpenUSD/pull/2086&#34;&gt;https://github.com/PixarAnimationStudios/OpenUSD/pull/2086&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Asset Structure Guidelines: &lt;a href=&#34;https://github.com/usd-wg/assets/blob/main/docs/asset-structure-guidelines.md&#34;&gt;https://github.com/usd-wg/assets/blob/main/docs/asset-structure-guidelines.md&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;where-to-find-more&#34;&gt;Where to Find More&lt;/h2&gt;
&lt;p&gt;Learning content hubs&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://openusd.org/&#34;&gt;https://openusd.org/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://developer.nvidia.com/usd&#34;&gt;https://developer.nvidia.com/usd&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://wiki.aswf.io/display/WGUSD/Learning+Content&#34;&gt;https://wiki.aswf.io/display/WGUSD/Learning+Content&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://developer.apple.com/search/?q=USD&#34;&gt;https://developer.apple.com/search/?q=USD&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;some-of-my-takeaways&#34;&gt;Some of My Takeaways&lt;/h2&gt;
&lt;p&gt;Some language clarifications from a programmer with no VFX experience. Keep in mind I AM NEW, my understanding may be off.&lt;/p&gt;
&lt;h3 id=&#34;prim&#34;&gt;Prim&lt;/h3&gt;
&lt;p&gt;A &amp;ldquo;Prim&amp;rdquo;, short for Primitive, refers to a node in the &lt;code&gt;Stage&lt;/code&gt; data structure, which appears to be a &lt;a href=&#34;https://en.wikipedia.org/wiki/Tree_(data_structure)&#34;&gt;tree&lt;/a&gt;. Nodes can conform to many types (Schemas). Any node of any type (Schema) is called a Prim, it appears. Prim is an instance of a Schema.&lt;/p&gt;
&lt;p&gt;UPDATE: The above is not strictly correct. Node type may actually be &lt;code&gt;SdfLayer&lt;/code&gt; not &lt;code&gt;UsdPrim&lt;/code&gt; under the hood? Both &lt;a href=&#34;https://github.com/PixarAnimationStudios/OpenUSD/blob/b53573ea2a6b29bc4a6b129f604bbb342c35df5c/pxr/usd/usd/stage.h#L147&#34;&gt;Stage&lt;/a&gt; and &lt;a href=&#34;https://github.com/PixarAnimationStudios/OpenUSD/blob/b53573ea2a6b29bc4a6b129f604bbb342c35df5c/pxr/usd/sdf/layer.h#L94&#34;&gt;SdfLayer&lt;/a&gt; conform to / inherit from public TfRefBase, public TfWeakBase which I have not followed up on but the comments on the linked to files were very helpful. I&amp;rsquo;m still feeling out the relationships here.&lt;/p&gt;
&lt;h3 id=&#34;layer&#34;&gt;Layer&lt;/h3&gt;
&lt;p&gt;A &amp;ldquo;Layer&amp;rdquo; is not a visual layer like in 2D graphics program for indicating visual information in front of something else. A &amp;ldquo;Layer&amp;rdquo; in USD serves as a modifier, much like &lt;code&gt;ViewModifier&lt;/code&gt; where the Prim gets passed through successive modifiers (layers). This is what its talking about when you see the key word &lt;code&gt;over&lt;/code&gt; instead of &lt;code&gt;def&lt;/code&gt; or &lt;code&gt;class&lt;/code&gt; in a prim declaration , that outer Prims features eat the ones inside it, when in conflict. The original prims don&amp;rsquo;t have their information changed, but the renderers/processors will discard their opinions.&lt;/p&gt;
&lt;p&gt;Prims can be referred to as being &amp;ldquo;composed of their Layer Stack&amp;rdquo;, ie they are what they ate.&lt;/p&gt;
&lt;h3 id=&#34;opinions&#34;&gt;Opinions&lt;/h3&gt;
&lt;p&gt;Values aren&amp;rsquo;t referred to as being &amp;ldquo;set&amp;rdquo; as much as a given prim is expressing it&amp;rsquo;s &lt;a href=&#34;https://remedy-entertainment.github.io/USDBook/terminology/opinions.html&#34;&gt;opinion&lt;/a&gt; in the layer stack. It&amp;rsquo;s opinion may not win. Opinion conflict resolution is what the whole &amp;ldquo;Non-destructive Composition Engine&amp;rdquo; thing is about, mediating how to consolidate all the different layers opinions about what should be on the Stage.&lt;/p&gt;
&lt;p&gt;For example if a particular opinion NEEDS to win it might be marked as a &lt;a href=&#34;https://remedy-entertainment.github.io/USDBook/terminology/specializes.html&#34;&gt;Specialization&lt;/a&gt;. Think css &amp;ldquo;&lt;a href=&#34;https://www.w3schools.com/css//css_important.asp&#34;&gt;!important&lt;/a&gt;&amp;rdquo; perhaps? In which case its the composition engine that discovers that and hands of the proper opinion to the renderer.&lt;/p&gt;
&lt;p&gt;The acronym &lt;code&gt;LIVRPS (Liver Peas)&lt;/code&gt; covers the negotiate order of precedence.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Local&lt;/li&gt;
&lt;li&gt;Inherits&lt;/li&gt;
&lt;li&gt;Variants&lt;/li&gt;
&lt;li&gt;References&lt;/li&gt;
&lt;li&gt;Payloads&lt;/li&gt;
&lt;li&gt;Specializes&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;schema&#34;&gt;Schema&lt;/h3&gt;
&lt;p&gt;The word schema came into English via Kant from the greek skhēma &amp;ldquo;figure, appearance, the nature of a thing&amp;rdquo; &lt;a href=&#34;https://www.etymonline.com/word/schema#etymonline_v_37688&#34;&gt;etymonline&lt;/a&gt;. &lt;a href=&#34;https://www.merriam-webster.com/dictionary/schema&#34;&gt;Websters&lt;/a&gt; now has an definition of it:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;a mental codification of experience that includes a particular organized way of perceiving cognitively and responding to a complex situation or set of stimuli&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;This seems apt here.&lt;/p&gt;
&lt;p&gt;Schemas in USD answer the questions &amp;ldquo;What is this thing&amp;hellip; conceptually?&amp;rdquo; and &amp;ldquo;How do I interact with this thing?&amp;rdquo; Pixar split its concept of Schemas into two kinds:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://remedy-entertainment.github.io/USDBook/terminology/isa_schemas.html&#34;&gt;IsA&lt;/a&gt;: which is a Class inheritance type relationship, i.e. a Type. &amp;ldquo;&lt;a href=&#34;https://openusd.org/release/tut_generating_new_schema.html&#34;&gt;imparts a typeName&lt;/a&gt;&amp;rdquo;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://remedy-entertainment.github.io/USDBook/terminology/api_schemas.html&#34;&gt;API&lt;/a&gt; A collection of behaviors that can act on a thing. Doesn&amp;rsquo;t impart a name but &lt;a href=&#34;https://openusd.org/release/tut_generating_new_schema.html&#34;&gt;&lt;code&gt;prim.HasAPI&lt;/code&gt; returns true&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Feels a little bit to me at the moment like a combination Classes/Structs, Protocols, and &lt;code&gt;extensions&lt;/code&gt; all rolled into one when one gets down to the implementation part.&lt;/p&gt;
&lt;p&gt;So a UsdGeoPrim &lt;em&gt;isA&lt;/em&gt; Xform (A Schema), but it can have a Material description applied to it via the &lt;em&gt;API&lt;/em&gt; MaterialBindingAPI (Also referred to as a Schema)&lt;/p&gt;
&lt;p&gt;Warning: USD does use the keyword &lt;code&gt;class&lt;/code&gt;, but it is used to create an instance of an Abstract Schema (one without visual content itself but may hold visual content).&lt;/p&gt;
&lt;h3 id=&#34;instance&#34;&gt;Instance&lt;/h3&gt;
&lt;p&gt;If you see the flag &lt;code&gt;instantiable&lt;/code&gt; It means something like to &amp;ldquo;the render doesn&amp;rsquo;t have to build me from scratch if its already built my Type before&amp;rdquo;.&lt;/p&gt;
&lt;h3 id=&#34;properties-vs-metadata-vs-attributes&#34;&gt;Properties vs Metadata vs Attributes&lt;/h3&gt;
&lt;p&gt;&lt;a href=&#34;https://remedy-entertainment.github.io/USDBook/terminology/properties.html&#34;&gt;Properties&lt;/a&gt; can be changed over time (think animations, think run time). &lt;a href=&#34;https://remedy-entertainment.github.io/USDBook/terminology/metadata.html&#34;&gt;Metadata&lt;/a&gt; cannot be changed (can be over-layed, think compile time).&lt;/p&gt;
&lt;p&gt;A subset of properties, &lt;a href=&#34;https://openusd.org/release/glossary.html#attribute&#34;&gt;Attributes&lt;/a&gt; appear to be properties that are &lt;a href=&#34;https://openusd.org/release/api/_usd__page__datatypes.html&#34;&gt;predefined by the spec&lt;/a&gt;, where a property in general could be a user defined key value pair.&lt;/p&gt;
&lt;h4 id=&#34;inside-a-usda-file&#34;&gt;Inside a USDA file&lt;/h4&gt;
&lt;p&gt;From what I can tell if it&amp;rsquo;s defined inside () it&amp;rsquo;s metadata, if it&amp;rsquo;s inside the {} it&amp;rsquo;s part a property. Properties can have associated metadata because properties are key:value pairs where the key is a String, but the value is what ever Schema you want.&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-usd&#34; data-lang=&#34;usd&#34;&gt;#usda 1.0
(
    //This is metadata
    defaultPrim = &amp;#34;my_shape&amp;#34;
)

def Xform &amp;#34;Rainbow&amp;#34; //&amp;lt;- prim Conforming to the IsA schema &amp;#34;Xform&amp;#34;
{
    def Cube &amp;#34;cube&amp;#34; //&amp;lt;- prim Conforming to the IsA schema &amp;#34;Cube&amp;#34;
    {
        //These are properties
        float3[] extent = [(-2, -2, -2), (2, 2, 2)]
        //This property has meta data and a name space (primvars:)
         color3f[] primvars:displayColor = [(0, 0, 1), (1,0,1), (1,0,0), (0, 1, 0),(0, 0, 1), (1,0,1), (1,0,0), (0, 1, 0)](
          interpolation = &amp;#34;vertex&amp;#34;
        )
    }
}
&lt;/code&gt;&lt;/pre&gt;&lt;h4 id=&#34;examples-from-the-spec&#34;&gt;Examples from the Spec&lt;/h4&gt;
&lt;p&gt;A &lt;a href=&#34;https://remedy-entertainment.github.io/USDBook/terminology/kind.html&#34;&gt;&lt;code&gt;kind&lt;/code&gt;&lt;/a&gt; is a type of metadata that tags prims with their roll for use during stage traversal. (&lt;code&gt;assemblage&lt;/code&gt;, &lt;code&gt;group&lt;/code&gt;). These a &lt;code&gt;kind&lt;/code&gt; can be user defined.&lt;/p&gt;
&lt;p&gt;A &lt;a href=&#34;https://remedy-entertainment.github.io/USDBook/terminology/purpose.html&#34;&gt;&lt;code&gt;purpose&lt;/code&gt;&lt;/a&gt; on the other hand is an attribute for the renderer to know if its there to be drawn or not. These are not user definable. (&lt;code&gt;default&lt;/code&gt;, &lt;code&gt;guide&lt;/code&gt;, &lt;code&gt;proxy&lt;/code&gt;, &lt;code&gt;render&lt;/code&gt;)&lt;/p&gt;
&lt;h2 id=&#34;what-this-means-for-the-dsl&#34;&gt;What this means for the DSL&lt;/h2&gt;
&lt;p&gt;Trouble. Pretty straight forward I think to create something that can punt out simpler p5js/Processing style generative art to a &lt;em&gt;flat&lt;/em&gt; USD file. But will I really be able to create a multi-file/multilayer USD with references that preserves the composition philosophy? (Inhales sharply) TDB. ARKit doesn&amp;rsquo;t event want that, but being true to the spirit of USD seems like a good goal.&lt;/p&gt;
&lt;p&gt;It would really help to have the Pixar Library as a Package, but even I think using that as a &amp;ldquo;My First Swift C++ Wrapper&amp;rdquo; project would be bad news. More tenable might be &amp;ldquo;My First Swift Python Wrapper&amp;rdquo;? Is that a thing?&lt;/p&gt;
</description>
    </item>
    
    
    
    <item>
      <title>Hello USD - Part 9: Parlez vous MultiBall? DSL starts here</title>
      <link>https://whynotestflight.com/excuses/hello-usd-part-9-parlez-vous-multiball-dsl-starts-here/</link>
      <pubDate>Thu, 13 Jul 2023 00:00:00 +0000</pubDate>
      
      <guid>https://whynotestflight.com/excuses/hello-usd-part-9-parlez-vous-multiball-dsl-starts-here/</guid>
      <description>&lt;p&gt;Wanna really never ship? Start writing a Domain Specific Language&amp;hellip;&lt;/p&gt;
&lt;p&gt;Honestly though, Swift enables doing that fairly easily with &lt;a href=&#34;&#34;&gt;&lt;code&gt;ResultBuilders&lt;/code&gt;&lt;/a&gt;, already in use in this project with &lt;code&gt;StringBuilder&lt;/code&gt;. I&amp;rsquo;m assuming the reader has at least heard of ResultBuilders. &lt;code&gt;SwiftUI&lt;/code&gt; uses them for &lt;code&gt;View&lt;/code&gt; creation, for example. References provided in case they are totally new.&lt;/p&gt;
&lt;p&gt;Today&amp;rsquo;s post documents the creation of &lt;code&gt;CanvasBuilder&lt;/code&gt;. For this post it will be using the concrete type Sphere instead of its future TDB more abstract type because ResultBuilders are MUCH simpler with concrete types, although that has &lt;a href=&#34;https://forums.swift.org/t/improved-result-builder-implementation-in-swift-5-8/63192&#34;&gt;recently improved&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I used this code:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;MultiBallStage&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;init&lt;/span&gt;(&lt;span style=&#34;color:#91d7e3&#34;&gt;count&lt;/span&gt;:&lt;span style=&#34;color:#91d7e3&#34;&gt;Int&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;.&lt;span style=&#34;color:#91d7e3&#34;&gt;count&lt;/span&gt; = &lt;span style=&#34;color:#91d7e3&#34;&gt;count&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;count&lt;/span&gt;:&lt;span style=&#34;color:#91d7e3&#34;&gt;Int&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;minTranslate&lt;/span&gt; = &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;-&lt;/span&gt;&lt;span style=&#34;color:#f5a97f&#34;&gt;4.0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;maxTranslate&lt;/span&gt; = &lt;span style=&#34;color:#f5a97f&#34;&gt;4.0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;     &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;minRadius&lt;/span&gt; = &lt;span style=&#34;color:#f5a97f&#34;&gt;0.8&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;     &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;maxRadius&lt;/span&gt; = &lt;span style=&#34;color:#f5a97f&#34;&gt;2.0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;buildStage&lt;/span&gt;() -&amp;gt; Canvas3D {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        Canvas3D {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//blue origin sphere&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            Sphere(radius: &lt;span style=&#34;color:#f5a97f&#34;&gt;1.0&lt;/span&gt;).color(red: &lt;span style=&#34;color:#f5a97f&#34;&gt;0&lt;/span&gt;, green: &lt;span style=&#34;color:#f5a97f&#34;&gt;0&lt;/span&gt;, blue: &lt;span style=&#34;color:#f5a97f&#34;&gt;1.0&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//the multi in multiball&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;for&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;0.&lt;/span&gt;.&amp;lt;&lt;span style=&#34;color:#91d7e3&#34;&gt;count&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                Sphere(radius: &lt;span style=&#34;color:#91d7e3&#34;&gt;Double&lt;/span&gt;.random(&lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt;: minRadius...maxRadius))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                .color(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    red: &lt;span style=&#34;color:#91d7e3&#34;&gt;Double&lt;/span&gt;.random(&lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt;: &lt;span style=&#34;color:#f5a97f&#34;&gt;0.&lt;/span&gt;..&lt;span style=&#34;color:#f5a97f&#34;&gt;1&lt;/span&gt;), 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    green: &lt;span style=&#34;color:#91d7e3&#34;&gt;Double&lt;/span&gt;.random(&lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt;: &lt;span style=&#34;color:#f5a97f&#34;&gt;0.&lt;/span&gt;..&lt;span style=&#34;color:#f5a97f&#34;&gt;1&lt;/span&gt;), 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    blue: &lt;span style=&#34;color:#91d7e3&#34;&gt;Double&lt;/span&gt;.random(&lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt;: &lt;span style=&#34;color:#f5a97f&#34;&gt;0.&lt;/span&gt;..&lt;span style=&#34;color:#f5a97f&#34;&gt;1&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                )
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                .translateBy(Vector.random(range: minTranslate...maxTranslate))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    } 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;To create this USDA file&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;DSL_multiball.png&#34; alt=&#34;13 spheres again, new colors and new layout&#34;&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;multiball_20230712T152941.usda&#34;&gt;raw file&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;A difference to classic multiball? Its all one file. No references. That&amp;rsquo;s a feature for another day.&lt;/p&gt;
&lt;h2 id=&#34;setup-info&#34;&gt;Setup Info&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Xcode 14.3.1&lt;/li&gt;
&lt;li&gt;MacOS 13.4.1&lt;/li&gt;
&lt;li&gt;Swift 5.8.1&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;references&#34;&gt;References&lt;/h2&gt;
&lt;p&gt;Relevant Repos:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/carlynorama/USDHelloWorld&#34;&gt;USDHelloWorld&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/carlynorama/SketchPad&#34;&gt;SketchPad&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Basics:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://www.hackingwithswift.com/swift/5.4/result-builders&#34;&gt;https://www.hackingwithswift.com/swift/5.4/result-builders&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://www.avanderlee.com/swift/result-builders/&#34;&gt;https://www.avanderlee.com/swift/result-builders/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Excellent Example:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Write a DSL in Swift using result builders: &lt;a href=&#34;https://developer.apple.com/videos/play/wwdc2021/10253/&#34;&gt;https://developer.apple.com/videos/play/wwdc2021/10253/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Fruta Example Code: &lt;a href=&#34;https://developer.apple.com/documentation/swiftui/fruta_building_a_feature-rich_app_with_swiftui&#34;&gt;https://developer.apple.com/documentation/swiftui/fruta_building_a_feature-rich_app_with_swiftui&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;More:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/apple/swift-evolution/blob/main/proposals/0289-result-builders.md&#34;&gt;https://github.com/apple/swift-evolution/blob/main/proposals/0289-result-builders.md&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;New in 5.8 features: &lt;a href=&#34;https://forums.swift.org/t/improved-result-builder-implementation-in-swift-5-8/63192&#34;&gt;https://forums.swift.org/t/improved-result-builder-implementation-in-swift-5-8/63192&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/apple/swift-evolution/blob/main/proposals/0289-result-builders.md&#34;&gt;https://github.com/apple/swift-evolution/blob/main/proposals/0289-result-builders.md&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/carson-katri/awesome-result-builders&#34;&gt;https://github.com/carson-katri/awesome-result-builders&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;TODO:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://www.pointfree.co/clips/815143145&#34;&gt;https://www.pointfree.co/clips/815143145&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/pointfreeco/swift-validated&#34;&gt;https://github.com/pointfreeco/swift-validated&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://talk.objc.io/episodes/S01E343-swiftui-style-backend-library&#34;&gt;https://talk.objc.io/episodes/S01E343-swiftui-style-backend-library&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://talk.objc.io/episodes/S01E337-attributed-string-builder-part-1&#34;&gt;https://talk.objc.io/episodes/S01E337-attributed-string-builder-part-1&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;non-string-custom-type-result-builder&#34;&gt;Non-String Custom Type Result Builder&lt;/h2&gt;
&lt;p&gt;It was kind of trick to find examples of &lt;code&gt;ResultBuilder&lt;/code&gt;s that weren&amp;rsquo;t concatenating &lt;code&gt;String&lt;/code&gt;s. &lt;code&gt;String&lt;/code&gt; has a bit of recursion in that a &lt;code&gt;String&lt;/code&gt; is both a single thing and a &lt;code&gt;Sequence&lt;/code&gt; itself.  A &lt;code&gt;Sphere&lt;/code&gt;, on the other hand, can never be a collection of &lt;code&gt;Sphere&lt;/code&gt;s, so the &lt;code&gt;String&lt;/code&gt; based examples didn&amp;rsquo;t show me everything I needed.&lt;/p&gt;
&lt;p&gt;Running the following code in a Playground prints the number 14 to the console.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// The fundamental type&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;Question&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;question&lt;/span&gt; = &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;What is the meaning of life, the universe, everything?&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;answer&lt;/span&gt;:&lt;span style=&#34;color:#91d7e3&#34;&gt;Int&lt;/span&gt; = &lt;span style=&#34;color:#f5a97f&#34;&gt;42&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// The distinct container type&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;Exam&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;content&lt;/span&gt;:[Question]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;init&lt;/span&gt;(@TestBuilder content: () -&amp;gt; [Question]) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;.content = content()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;@resultBuilder
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;enum&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;TestBuilder&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// Essential&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// Don&amp;#39;t use (_ components: Question...) -&amp;gt; [Question] { components }&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;buildBlock&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; components: [Question]...) -&amp;gt; [Question] {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        components.flatMap { &lt;span style=&#34;color:#f4dbd6&#34;&gt;$0&lt;/span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// Allows for using both arrays and single items&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;buildExpression&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; expression: [Question]) -&amp;gt; [Question] {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        expression
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;buildExpression&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; expression: Question) -&amp;gt; [Question] {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        [expression]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// Allows if&amp;#39;s with no else&amp;#39;s&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;buildOptional&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; component: [Question]?) -&amp;gt; [Question] {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        component ?? []
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// Allows if-else statements&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;buildEither&lt;/span&gt;(&lt;span style=&#34;color:#91d7e3&#34;&gt;first&lt;/span&gt; component: [Question]) -&amp;gt; [Question] {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        component
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;buildEither&lt;/span&gt;(second component: [Question]) -&amp;gt; [Question] {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        component
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// Allows for loops&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;buildArray&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; components: [[Question]]) -&amp;gt; [Question] {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; components.flatMap { &lt;span style=&#34;color:#f4dbd6&#34;&gt;$0&lt;/span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;run&lt;/span&gt;(&lt;span style=&#34;color:#91d7e3&#34;&gt;count&lt;/span&gt;: &lt;span style=&#34;color:#91d7e3&#34;&gt;Int&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;build&lt;/span&gt; = Exam {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        Question()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        Question()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        Question()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;for&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;0.&lt;/span&gt;..&lt;span style=&#34;color:#f5a97f&#34;&gt;5&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            Question()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;5&lt;/span&gt; == &lt;span style=&#34;color:#91d7e3&#34;&gt;count&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            Question()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        } &lt;span style=&#34;color:#c6a0f6&#34;&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            Question()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            Question()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        [Question(), Question(), Question()]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(build.content.&lt;span style=&#34;color:#91d7e3&#34;&gt;count&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;run(&lt;span style=&#34;color:#91d7e3&#34;&gt;count&lt;/span&gt;: &lt;span style=&#34;color:#f5a97f&#34;&gt;3&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The only absolutely necessary function in th ResultBuilder is&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;buildBlock&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; components: [Question]...) -&amp;gt; [Question] {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    components.flatMap { &lt;span style=&#34;color:#f4dbd6&#34;&gt;$0&lt;/span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Using &lt;code&gt;(_ components: Question...) -&amp;gt; [Question] { components }&lt;/code&gt; works until any of the other functions are also implemented. Errors like &lt;code&gt;Cannot pass array of type &#39;[Sphere]&#39; as variadic arguments of type &#39;Sphere&#39;&lt;/code&gt; refer to this type miss-match that gets hidden in &lt;code&gt;String&lt;/code&gt; based examples.&lt;/p&gt;
&lt;h2 id=&#34;lining-the-dsl-up-with-usd&#34;&gt;Lining the DSL up with USD&lt;/h2&gt;
&lt;p&gt;The nice thing about Multiball is that it&amp;rsquo;s all Spheres, so I that&amp;rsquo;s only one concrete type needed in my Canvas for now.&lt;/p&gt;
&lt;p&gt;But what does that type look like and how does it work with USD Format output?&lt;/p&gt;
&lt;p&gt;First off we have the protocol &lt;code&gt;Geometry&lt;/code&gt; which mashes together &lt;code&gt;Boundable&lt;/code&gt;, &lt;code&gt;Surfaceble&lt;/code&gt; and &lt;code&gt;Transformable&lt;/code&gt;, which roughly translate to &lt;a href=&#34;https://openusd.org/release/api/class_usd_geom_boundable.html&#34;&gt;&lt;code&gt;UsdGeomBoundable&lt;/code&gt;&lt;/a&gt;, and I think &lt;a href=&#34;https://openusd.org/release/api/class_usd_geom_imageable.html&#34;&gt;&lt;code&gt;Imagable&lt;/code&gt;&lt;/a&gt; and &lt;a href=&#34;https://openusd.org/release/api/class_usd_geom_xform.html&#34;&gt;&lt;code&gt;Xform&lt;/code&gt;&lt;/a&gt;? It should end up feeling like &lt;a href=&#34;https://openusd.org/release/glossary.html#usdglossary-gprim&#34;&gt;&lt;code&gt;GPrim&lt;/code&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Boundable&lt;/code&gt; types can return a &lt;code&gt;Bounds3D&lt;/code&gt; modeled after  &lt;a href=&#34;https://developer.apple.com/documentation/modelio/mdlaxisalignedboundingbox&#34;&gt;mdlaxisalignedboundingbox&lt;/a&gt; and what USD files have written down as &lt;a href=&#34;https://openusd.org/release/api/boundable_compute_extent_8h.html&#34;&gt;Extent&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Transformable&lt;/code&gt; types are those things that can receive the common &lt;a href=&#34;https://www.3blue1brown.com/lessons/3d-transformations&#34;&gt;3D linear transformations&lt;/a&gt; (translate, rotate, scale).&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Surfacable&lt;/code&gt; for now means could one apply a material or a color to it. Hopefully one day a shader as well!&lt;/p&gt;
&lt;p&gt;The functions that apply surfaces and transform geometries cannot be mutating, but instead must return something that the CanvasBuilder will accept like &lt;a href=&#34;https://developer.apple.com/documentation/swiftui/viewmodifier&#34;&gt;ViewModifiers&lt;/a&gt; in &lt;code&gt;SwiftUI&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;In this, our proto CanvasBuilder, that means Spheres.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;protocol&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;Geometry&lt;/span&gt;:Transformable &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;amp;&lt;/span&gt; Boundable &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;amp;&lt;/span&gt; Surfaceable {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;id&lt;/span&gt;:&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt; { &lt;span style=&#34;color:#c6a0f6&#34;&gt;get&lt;/span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;shapeName&lt;/span&gt;:&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt; { &lt;span style=&#34;color:#c6a0f6&#34;&gt;get&lt;/span&gt; } &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//This might become an enum? &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;protocol&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;Boundable&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;currentBounds&lt;/span&gt;:Bounds3D { &lt;span style=&#34;color:#c6a0f6&#34;&gt;get&lt;/span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;Bounds3D&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;minBounds&lt;/span&gt;:Vector
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;maxBounds&lt;/span&gt;:Vector
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;enum&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;Transformation&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;case&lt;/span&gt; translate(Vector)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;protocol&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;Transformable&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;transformations&lt;/span&gt;:[Transformation] { &lt;span style=&#34;color:#c6a0f6&#34;&gt;get&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;set&lt;/span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;mutating&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;translateBy&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; vector:Vector) -&amp;gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;Self&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;extension&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;Transformable&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;translateBy&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; vector: Vector) -&amp;gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;Self&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;copy&lt;/span&gt; = &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        copy.transformations.append(.translate(vector))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; copy
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;enum&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;Surface&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;case&lt;/span&gt; diffuseColor((r:&lt;span style=&#34;color:#91d7e3&#34;&gt;Double&lt;/span&gt;, g:&lt;span style=&#34;color:#91d7e3&#34;&gt;Double&lt;/span&gt;, b:&lt;span style=&#34;color:#91d7e3&#34;&gt;Double&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;case&lt;/span&gt; emissiveColor((r:&lt;span style=&#34;color:#91d7e3&#34;&gt;Double&lt;/span&gt;, g:&lt;span style=&#34;color:#91d7e3&#34;&gt;Double&lt;/span&gt;, b:&lt;span style=&#34;color:#91d7e3&#34;&gt;Double&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;case&lt;/span&gt; metallic(&lt;span style=&#34;color:#91d7e3&#34;&gt;Double&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;case&lt;/span&gt; displayColor((r:&lt;span style=&#34;color:#91d7e3&#34;&gt;Double&lt;/span&gt;, g:&lt;span style=&#34;color:#91d7e3&#34;&gt;Double&lt;/span&gt;, b:&lt;span style=&#34;color:#91d7e3&#34;&gt;Double&lt;/span&gt;)) &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// Only one that matters for now.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;protocol&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;Surfaceable&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;surfaces&lt;/span&gt;:[Surface] { &lt;span style=&#34;color:#c6a0f6&#34;&gt;get&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;set&lt;/span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//func diffuseColor(red:Double, green:Double, blue:Double) -&amp;gt; Self&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//func emissiveColor(red:Double, green:Double, blue:Double) -&amp;gt; Self&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;color&lt;/span&gt;(red:&lt;span style=&#34;color:#91d7e3&#34;&gt;Double&lt;/span&gt;, green:&lt;span style=&#34;color:#91d7e3&#34;&gt;Double&lt;/span&gt;, blue:&lt;span style=&#34;color:#91d7e3&#34;&gt;Double&lt;/span&gt;) -&amp;gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;Self&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;extension&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;Surfaceable&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;color&lt;/span&gt;(red:&lt;span style=&#34;color:#91d7e3&#34;&gt;Double&lt;/span&gt;, green:&lt;span style=&#34;color:#91d7e3&#34;&gt;Double&lt;/span&gt;, blue:&lt;span style=&#34;color:#91d7e3&#34;&gt;Double&lt;/span&gt;) -&amp;gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;Self&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;copy&lt;/span&gt; = &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        copy.surfaces.append(.displayColor((red, green, blue)))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; copy
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The current implementation of sphere has a lot of boiler plate&amp;hellip; is this a possible future macro?&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;Sphere&lt;/span&gt;:Geometry {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;shapeName&lt;/span&gt; = &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Sphere&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//UUID are too long&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;id&lt;/span&gt;:&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt; = IdString.make(&lt;span style=&#34;color:#c6a0f6&#34;&gt;prefix&lt;/span&gt;: &lt;span style=&#34;color:#f5a97f&#34;&gt;Self&lt;/span&gt;.shapeName)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;radius&lt;/span&gt;:&lt;span style=&#34;color:#91d7e3&#34;&gt;Double&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;shapeName&lt;/span&gt;: &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f5a97f&#34;&gt;Self&lt;/span&gt;.shapeName
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;init&lt;/span&gt;(radius: &lt;span style=&#34;color:#91d7e3&#34;&gt;Double&lt;/span&gt;, transformations:[Transformation] = []) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;.radius = radius
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;.transformations = transformations
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//Boundable&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;currentBounds&lt;/span&gt;: Bounds3D {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;minVect&lt;/span&gt; = Vector(x: &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;-&lt;/span&gt;radius, y: &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;-&lt;/span&gt;radius, z: &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;-&lt;/span&gt;radius)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;maxVect&lt;/span&gt; = Vector(x: radius, y: radius, z: radius)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; Bounds3D(minBounds: minVect, maxBounds: maxVect)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//Transformable&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;transformations&lt;/span&gt;:[Transformation] = []
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//Surfaceable&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;surfaces&lt;/span&gt;:[Surface] = []
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Like with regular USD, the layout of all the spheres in the scene has to go to a &amp;ldquo;renderer&amp;rdquo;. Unlike with USD, I don&amp;rsquo;t have to do any Graphics Programming, I just need to mash text together.&lt;/p&gt;
&lt;p&gt;The New &lt;code&gt;USDAFileBuilder&lt;/code&gt; takes in a canvas and it&amp;rsquo;s attendant spheres and some meta data and uses that data structure to create a USD file with a lot more flexibility than the &lt;code&gt;USDAFileBuilder&lt;/code&gt;.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;Foundation&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;USDAFileBuilder&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;stage&lt;/span&gt;:Canvas3D
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;defaultPrimIndex&lt;/span&gt;:&lt;span style=&#34;color:#91d7e3&#34;&gt;Int&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;metersPerUnit&lt;/span&gt;:&lt;span style=&#34;color:#91d7e3&#34;&gt;Int&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;upAxis&lt;/span&gt;:&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;documentationNote&lt;/span&gt;:&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;?
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;init&lt;/span&gt;(stage: Canvas3D, 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    defaultPrimIndex: &lt;span style=&#34;color:#91d7e3&#34;&gt;Int&lt;/span&gt; = &lt;span style=&#34;color:#f5a97f&#34;&gt;0&lt;/span&gt;, 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    metersPerUnit: &lt;span style=&#34;color:#91d7e3&#34;&gt;Int&lt;/span&gt; = &lt;span style=&#34;color:#f5a97f&#34;&gt;1&lt;/span&gt;, 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    upAxis: &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt; = &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Y&amp;#34;&lt;/span&gt;, 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    docNote:&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;? = &lt;span style=&#34;color:#f5a97f&#34;&gt;nil&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;.stage = stage
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;.defaultPrimIndex = defaultPrimIndex
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;.metersPerUnit = metersPerUnit
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;.upAxis = upAxis
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;.documentationNote = docNote
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        @StringBuilder &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;generateHeader&lt;/span&gt;() -&amp;gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;#usda 1.0&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\n&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;(&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\t&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;defaultPrim = &lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;stage.content[defaultPrimIndex].id&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\t&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;metersPerUnit = &lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;metersPerUnit&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\t&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;upAxis = &lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;upAxis&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;documentationNote&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;doc = &lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;documentationNote&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;)&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;colorString&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; red:&lt;span style=&#34;color:#91d7e3&#34;&gt;Double&lt;/span&gt;, &lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; green:&lt;span style=&#34;color:#91d7e3&#34;&gt;Double&lt;/span&gt;, &lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; blue:&lt;span style=&#34;color:#91d7e3&#34;&gt;Double&lt;/span&gt;) -&amp;gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;color3f[] primvars:displayColor = [(&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;red&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;, &lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;green&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;, &lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;blue&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;)]&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;colorString&lt;/span&gt;(shape:Geometry) -&amp;gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//There has been a problem. &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; shape.surfaces.&lt;span style=&#34;color:#91d7e3&#34;&gt;count&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;!=&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;1&lt;/span&gt; { &lt;span style=&#34;color:#91d7e3&#34;&gt;fatalError&lt;/span&gt;() }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;color&lt;/span&gt; = shape.surfaces[&lt;span style=&#34;color:#f5a97f&#34;&gt;0&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;switch&lt;/span&gt; color {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#c6a0f6&#34;&gt;case&lt;/span&gt; .displayColor(&lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;c&lt;/span&gt;):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\t\t&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;colorString&lt;span style=&#34;color:#a6da95&#34;&gt;(&lt;/span&gt;c.r, c.g, c.b&lt;span style=&#34;color:#a6da95&#34;&gt;))&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#c6a0f6&#34;&gt;default&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    &lt;span style=&#34;color:#91d7e3&#34;&gt;fatalError&lt;/span&gt;()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt;  &lt;span style=&#34;color:#8aadf4&#34;&gt;radiusString&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; radius:&lt;span style=&#34;color:#91d7e3&#34;&gt;Double&lt;/span&gt;) -&amp;gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;double radius = &lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;radius&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;extentString&lt;/span&gt;(shape:Geometry) -&amp;gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;minBounds&lt;/span&gt; = shape.currentBounds.minBounds
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;maxBounds&lt;/span&gt; = shape.currentBounds.maxBounds
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;float3[] extent = [(&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;minBounds.x&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;, &lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;minBounds.y&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;, &lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;minBounds.z&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;), (&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;maxBounds.x&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;, &lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;maxBounds.y&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;, &lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;maxBounds.z&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;)]&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;TODO:&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt; Right now, can do the one and only one transform&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;transformString&lt;/span&gt;(shape:Geometry) -&amp;gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; shape.transformations.&lt;span style=&#34;color:#91d7e3&#34;&gt;count&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;!=&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;1&lt;/span&gt; { &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;translate&lt;/span&gt; = shape.transformations[&lt;span style=&#34;color:#f5a97f&#34;&gt;0&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;switch&lt;/span&gt; translate {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#c6a0f6&#34;&gt;case&lt;/span&gt; .translate(&lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;v&lt;/span&gt;):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&amp;#34;&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;                &lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\t\t&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;double3 xformOp:translate = (&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;v.x&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;, &lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;v.y&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;, &lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;v.z&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;                &lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\t\t&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;uniform token[] xformOpOrder = [&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;xformOp:translate&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;                &amp;#34;&amp;#34;&amp;#34;&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        @StringBuilder &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;sphereBuilder&lt;/span&gt;(shape:Sphere) -&amp;gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;def Xform &lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;shape.id&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\&amp;#34;\n&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;{&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//&amp;#34;def Xform \&amp;#34;\(shape.shapeName)_\(shape.id)\&amp;#34;\n{&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;!&lt;/span&gt;shape.transformations.&lt;span style=&#34;color:#91d7e3&#34;&gt;isEmpty&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                transformString(shape:shape) 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//&amp;#34;\tdef \(shape.shapeName) \&amp;#34;\(shape.shapeName.lowercased())_\(shape.id)\&amp;#34;\n\t{&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\t&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;def &lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;shape.shapeName&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;shape.id.lowercased&lt;span style=&#34;color:#a6da95&#34;&gt;())&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\&amp;#34;\n\t&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;{&amp;#34;&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\t\t&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;extentString&lt;span style=&#34;color:#a6da95&#34;&gt;(&lt;/span&gt;shape: shape&lt;span style=&#34;color:#a6da95&#34;&gt;))&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;TODO:&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt; How to handle surfaces more generally&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;!&lt;/span&gt;shape.surfaces.&lt;span style=&#34;color:#91d7e3&#34;&gt;isEmpty&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                colorString(shape:shape)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//This is what makes it a SPHERE builder.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\t\t&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;radiusString&lt;span style=&#34;color:#a6da95&#34;&gt;(&lt;/span&gt;shape.radius&lt;span style=&#34;color:#a6da95&#34;&gt;))&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\t&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;}&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;}&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        @StringBuilder &lt;span style=&#34;color:#ed8796&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;generateStringFromStage&lt;/span&gt;() -&amp;gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            generateHeader()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;for&lt;/span&gt; item &lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt; stage.content {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                sphereBuilder(shape: item)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;getting-and-saving-the-result&#34;&gt;Getting and Saving the Result&lt;/h2&gt;
&lt;p&gt;For now the CLI creates a MultiBallStage struct passing in the count and then requests the output of the &lt;code&gt;generateStringFromStage()&lt;/code&gt; function, saving it to a file. Everything else in the CLI remains the same.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;fileBuilder&lt;/span&gt; = USDAFileBuilder(stage: MultiBallStage(&lt;span style=&#34;color:#91d7e3&#34;&gt;count&lt;/span&gt;:&lt;span style=&#34;color:#91d7e3&#34;&gt;count&lt;/span&gt;).buildStage())
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;fileString&lt;/span&gt;:&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt; = fileBuilder.generateStringFromStage()
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;next-time-on-why-no-test-flight&#34;&gt;Next time on Why No Test Flight&amp;hellip;&lt;/h2&gt;
&lt;p&gt;It&amp;rsquo;s a mess, but I made a matching X3D FileBuilder as well.&lt;/p&gt;
&lt;script type=&#39;text/javascript&#39; src=&#39;https://www.x3dom.org/download/x3dom.js&#39;&gt; &lt;/script&gt; 
&lt;x3d width=&#39;500px&#39; height=&#39;400px&#39;&gt; 
&lt;scene&gt;
&lt;inline url=&#34;multiball_20230713T072435.x3d&#34;&gt; &lt;/inline&gt; 
&lt;/scene&gt; 
&lt;/x3d&gt; 
&lt;p&gt;&lt;a href=&#34;multiball_20230713T072435.x3d&#34;&gt;raw file&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;usd_matching_x3d.png&#34; alt=&#34;Screenshot of QuickLook preview of USD file full of multi colored spheres that matches the embedded X3D file above. That the spheres are lower-poly meshes is of note.&#34;&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;multiball_20230713T072435.usda&#34;&gt;raw file&lt;/a&gt;&lt;/p&gt;
</description>
    </item>
    
    
    
    <item>
      <title>Hello USD - Part 8: Multiball moves to a Package</title>
      <link>https://whynotestflight.com/excuses/hello-usd-part-8-multiball-moves-to-a-package/</link>
      <pubDate>Wed, 12 Jul 2023 00:00:00 +0000</pubDate>
      
      <guid>https://whynotestflight.com/excuses/hello-usd-part-8-multiball-moves-to-a-package/</guid>
      <description>&lt;p&gt;I&amp;rsquo;ve been punking code and examples into &lt;a href=&#34;https://github.com/carlynorama/USDHelloWorld&#34;&gt;USDHelloWorld&lt;/a&gt;. I will still be putting example usd files and support scripts in that repo, but I wanted something more reusable/evolvable.&lt;/p&gt;
&lt;p&gt;Enter new dual-product repo &lt;a href=&#34;https://github.com/carlynorama/SketchPad&#34;&gt;SketchPad&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This new repo contains a Library and and executable CLI. This post will be pretty thin on the USD stuff because I&amp;rsquo;m just, once again, recreating the multiball example.&lt;/p&gt;
&lt;p&gt;Other public repos with ArgumentParser:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/carlynorama/tipsy-robot-swift&#34;&gt;https://github.com/carlynorama/tipsy-robot-swift&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/carlynorama/clipng&#34;&gt;https://github.com/carlynorama/clipng&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src=&#34;package_multiball.png&#34; alt=&#34;Spheres of various colors and sizes strewn about a blank canvas&#34;&gt;&lt;/p&gt;
&lt;p&gt;Tomorrow will focus more on using ResultBuilder to help make creating a generative USD easier.&lt;/p&gt;
&lt;h2 id=&#34;argumentparser-references&#34;&gt;ArgumentParser References&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://swiftpackageindex.com/apple/swift-argument-parser/1.2.2/documentation/argumentparser/gettingstarted&#34;&gt;https://swiftpackageindex.com/apple/swift-argument-parser/1.2.2/documentation/argumentparser/gettingstarted&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://www.swift.org/blog/argument-parser/&#34;&gt;https://www.swift.org/blog/argument-parser/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://www.youtube.com/watch?v=pQt71tLmiac&#34;&gt;https://www.youtube.com/watch?v=pQt71tLmiac&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;getting-started&#34;&gt;Getting Started&lt;/h2&gt;
&lt;p&gt;My usual process for creating an executable package:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-zsh&#34; data-lang=&#34;zsh&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;mkdir &lt;span style=&#34;color:#f4dbd6&#34;&gt;$NAME&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#91d7e3&#34;&gt;cd&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;$NAME&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;git init
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;git branch -M main
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;touch README.md
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;swift package init --type executable
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;touch .gitattributes
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#touch .env #&amp;lt;- not used every repo&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;swift run
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## Update .gitignore and .gitattributes&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;git add .
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;git commit -m &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;hello project&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## Options for making a remote:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## https://cli.github.com/manual/gh_repo_create  (brew install gh)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#gh repo create $NAME --public&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#git remote add origin $REPO_URL  ## &amp;lt;- links an existing repo to git&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#git remote -v #checks to see if it worked&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## Potential GOTCHAs - https://docs.github.com/en/authentication/troubleshooting-ssh/error-permission-denied-publickey#make-sure-you-have-a-key-that-is-being-used&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;git push -u origin main
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;gitignore&#34;&gt;.gitignore&lt;/h3&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;# ------ generated by package init.
.DS_Store
/.build
/Packages
/*.xcodeproj
xcuserdata/
DerivedData/
.swiftpm/config/registries.json
.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata
.netrc

## ----------- added

# VSCode
.vscode

# Secrets &amp;amp; Environment
.env

# Swift additional
Package.resolved

# Python (not used but its been known to sneak in...)
__pycache__/
*.py[cod]
*$py.class
&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=&#34;gitattributes&#34;&gt;.gitattributes&lt;/h3&gt;
&lt;p&gt;Helpful for multi-platform work. Gets ugly when not there from the beginning.&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;# Auto detect text files and perform LF normalization
* text=auto
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&#34;changes-to-the-package-file&#34;&gt;Changes to the Package File&lt;/h2&gt;
&lt;p&gt;Because I want a library and and CLI I made some changes to the Package file. In the code base the files for each target have their own folder named the same as the target name. The library must be listed as a dependency for the CLI.&lt;/p&gt;
&lt;p&gt;Typically I&amp;rsquo;d have the Library in its own Package, but since this is all very fast changing for now they live together.&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;Sources -------- SketchPad
            |
             --- SketchPadCLI
&lt;/code&gt;&lt;/pre&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;package&lt;/span&gt; = Package(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    name: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;SketchPad&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// &lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;TODO:&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt; This might make somethings easier. &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// platforms: [&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//     .macOS(.v10_15),&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// ],&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    products: [
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        .library(name: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;SketchPad&amp;#34;&lt;/span&gt;, targets: [&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;SketchPad&amp;#34;&lt;/span&gt;]),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        .executable(name: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;sketchpad&amp;#34;&lt;/span&gt;, targets: [&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;SketchPadCLI&amp;#34;&lt;/span&gt;])
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    ],
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    dependencies: [
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        .package(url: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;https://github.com/apple/swift-argument-parser.git&amp;#34;&lt;/span&gt;, from: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;1.2.2&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    ],
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    targets: [
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;         .target(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            name: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;SketchPad&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;         ),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;         .executableTarget(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            name: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;SketchPadCLI&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            dependencies: [
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;SketchPad&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                .product(name: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;ArgumentParser&amp;#34;&lt;/span&gt;, package: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;swift-argument-parser&amp;#34;&lt;/span&gt;),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            ]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;         )
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    ]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;recreate-multiball---cli&#34;&gt;Recreate Multiball - CLI&lt;/h2&gt;
&lt;h3 id=&#34;mainswift&#34;&gt;main.swift&lt;/h3&gt;
&lt;p&gt;Again taking advantage of the convenience of a main.swift, but this time a lot less goes in it. &lt;code&gt;multiball&lt;/code&gt; gets set up as a sub command because I know I will be making more, but for now it gets set as the default.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;Foundation&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;ArgumentParser&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;SketchPadCLI&lt;/span&gt;: ParsableCommand {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;     &lt;span style=&#34;color:#ed8796&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;configuration&lt;/span&gt; = CommandConfiguration(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        abstract: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;A Swift command-line tool to create 3D files from simple instructions&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        version: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;0.0.1&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        subcommands: [
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            multiball.&lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        ],
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        defaultSubcommand: multiball.&lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;init&lt;/span&gt;() { }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;SketchPadCLI.main()
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;multiballswift&#34;&gt;multiball.swift&lt;/h3&gt;
&lt;p&gt;None of the logic for building the USD file lives in my UI code, even if it is a command line UI.&lt;/p&gt;
&lt;p&gt;With ArgumentParser, I can create CLI tools with a &lt;code&gt;--help&lt;/code&gt; feature really easily, which is why I use it.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;extension&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;SketchPadCLI&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;multiball&lt;/span&gt;:ParsableCommand {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        @Flag(name: [.customLong(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;save&amp;#34;&lt;/span&gt;), .customShort(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;s&amp;#34;&lt;/span&gt;)], help: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Will save to file called &lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;multiball_$TIMESTAMP.usda&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt; instead of printing to stdout&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;saveToFile&lt;/span&gt; = &lt;span style=&#34;color:#f5a97f&#34;&gt;false&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        @Option(name: [.customLong(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;output&amp;#34;&lt;/span&gt;), .customShort(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;o&amp;#34;&lt;/span&gt;)], help: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Will save to custom path instead of printing to stdout&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;customPath&lt;/span&gt;:&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;? = &lt;span style=&#34;color:#f5a97f&#34;&gt;nil&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        @Option(name: [.customLong(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;count&amp;#34;&lt;/span&gt;), .customShort(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;c&amp;#34;&lt;/span&gt;)],
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;              help: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Number of spheres to generate in addition to the blue origin sphere. Default is 12&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;count&lt;/span&gt;:&lt;span style=&#34;color:#91d7e3&#34;&gt;Int&lt;/span&gt; = &lt;span style=&#34;color:#f5a97f&#34;&gt;12&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;configuration&lt;/span&gt; =
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        CommandConfiguration(abstract: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Generate a USDA file that references sphere_base.usda like previous examples. 12 + blue origin ball is the default count&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;run&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;fileString&lt;/span&gt; = generateMultiBallUSDText(&lt;span style=&#34;color:#91d7e3&#34;&gt;count&lt;/span&gt;:&lt;span style=&#34;color:#91d7e3&#34;&gt;count&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; saveToFile &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;||&lt;/span&gt; customPath &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;!=&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;nil&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#c6a0f6&#34;&gt;do&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    &lt;span style=&#34;color:#c6a0f6&#34;&gt;guard&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;data&lt;/span&gt;:Data = fileString.data(using: .utf8) &lt;span style=&#34;color:#c6a0f6&#34;&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                        &lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Could not encode string to data&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                        &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;path&lt;/span&gt;:&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt; = customPath ?? &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;multiball_&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;FileIO.timeStamp&lt;span style=&#34;color:#a6da95&#34;&gt;())&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;.usda&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; FileIO.writeToFile(data: data, filePath: path)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                } &lt;span style=&#34;color:#c6a0f6&#34;&gt;catch&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    &lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Could not write data to file: &lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;error&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            } &lt;span style=&#34;color:#c6a0f6&#34;&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(fileString)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;fileioswift&#34;&gt;FileIO.swift&lt;/h3&gt;
&lt;p&gt;Since I tend to cross compile on Linux I have some helper FileIO functions. TDB if they will still be needed with the new Foundation. This isn&amp;rsquo;t the whole file, just what&amp;rsquo;s being used.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;Foundation&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;enum&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;FileIO&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;timeStamp&lt;/span&gt;() -&amp;gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;formatter&lt;/span&gt; = DateFormatter()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        formatter.dateFormat = &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;YYYYMMdd&amp;#39;T&amp;#39;HHmmss&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; formatter.string(from: Date()) &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//&amp;lt;- &lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;TODO:&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt; confirm that is &amp;#34;now&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;makeFileURL&lt;/span&gt;(filePath:&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;) -&amp;gt; URL {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;TODO:&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt; For iOS??&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//let locationToWrite = URL.documentsDirectory.appendingPathComponent(&amp;#34;testImage&amp;#34;, conformingTo: .png)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#if&lt;/span&gt; &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;os&lt;/span&gt;(&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;Linux&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; URL(fileURLWithPath: filePath)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#else&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#available&lt;/span&gt;(&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;macOS&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;13.0&lt;/span&gt;, &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;*&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; URL(filePath: filePath)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        } &lt;span style=&#34;color:#c6a0f6&#34;&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// Fallback on earlier versions&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;             &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; URL(fileURLWithPath: filePath)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#endif&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;writeToFile&lt;/span&gt;(data:Data , filePath:&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;) &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;url&lt;/span&gt; = makeFileURL(filePath: filePath)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; data.write(to: url)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;writeToFile&lt;/span&gt;(string:&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;, filePath:&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;? = &lt;span style=&#34;color:#f5a97f&#34;&gt;nil&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;path&lt;/span&gt; = filePath ?? &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;text_&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;timeStamp&lt;span style=&#34;color:#a6da95&#34;&gt;())&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;.txt&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;do&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;guard&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;data&lt;/span&gt;:Data = string.data(using: .utf8) &lt;span style=&#34;color:#c6a0f6&#34;&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Could not encode string to data&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; FileIO.writeToFile(data: data, filePath: path)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        } &lt;span style=&#34;color:#c6a0f6&#34;&gt;catch&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Could not write data to file: &lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;error&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;recreate-multiball---guts&#34;&gt;Recreate multiball - Guts&lt;/h2&gt;
&lt;p&gt;The actual logic lives in the &lt;code&gt;MultiBall.swift&lt;/code&gt; file in the library&amp;rsquo;s source directory.&lt;/p&gt;
&lt;p&gt;This code will look very familiar from &lt;a href=&#34;https://whynotestflight.com/excuses/hello-usd-part-6-same-as-part-1...-but-swift/&#34;&gt;Part 6&lt;/a&gt;, but since it will be vaporized shortly to make way for a new approach, I&amp;rsquo;ll save it here for posterity.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;Foundation&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;generateMultiBallUSDText&lt;/span&gt;(&lt;span style=&#34;color:#91d7e3&#34;&gt;count&lt;/span&gt;:&lt;span style=&#34;color:#91d7e3&#34;&gt;Int&lt;/span&gt;) -&amp;gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;     &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;minX&lt;/span&gt; = &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;-&lt;/span&gt;&lt;span style=&#34;color:#f5a97f&#34;&gt;4.0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;     &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;maxX&lt;/span&gt; = &lt;span style=&#34;color:#f5a97f&#34;&gt;4.0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;     &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;minY&lt;/span&gt; = minX
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;     &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;maxY&lt;/span&gt; = maxX
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;     &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;minZ&lt;/span&gt; = minX
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;     &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;maxZ&lt;/span&gt; = maxX
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;     &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;minRadius&lt;/span&gt; = &lt;span style=&#34;color:#f5a97f&#34;&gt;0.8&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;     &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;maxRadius&lt;/span&gt; = &lt;span style=&#34;color:#f5a97f&#34;&gt;2.0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;     @StringBuilder &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt;  &lt;span style=&#34;color:#8aadf4&#34;&gt;makeMultiBall&lt;/span&gt;(&lt;span style=&#34;color:#91d7e3&#34;&gt;count&lt;/span&gt;:&lt;span style=&#34;color:#91d7e3&#34;&gt;Int&lt;/span&gt;) -&amp;gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;         &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;builder&lt;/span&gt; = USDAFileBuilder()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;         builder.generateHeader(defaultPrim:&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;blueSphere&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;         builder.buildItem(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;blueSphere&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;sphere_base&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;sphere&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#f5a97f&#34;&gt;0&lt;/span&gt;, &lt;span style=&#34;color:#f5a97f&#34;&gt;0&lt;/span&gt;, &lt;span style=&#34;color:#f5a97f&#34;&gt;0&lt;/span&gt;, &lt;span style=&#34;color:#f5a97f&#34;&gt;1&lt;/span&gt;, &lt;span style=&#34;color:#f5a97f&#34;&gt;0&lt;/span&gt;, &lt;span style=&#34;color:#f5a97f&#34;&gt;0&lt;/span&gt;, &lt;span style=&#34;color:#f5a97f&#34;&gt;1&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;         &lt;span style=&#34;color:#c6a0f6&#34;&gt;for&lt;/span&gt; i &lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt; (&lt;span style=&#34;color:#f5a97f&#34;&gt;0.&lt;/span&gt;..&lt;span style=&#34;color:#91d7e3&#34;&gt;count&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;-&lt;/span&gt;&lt;span style=&#34;color:#f5a97f&#34;&gt;1&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;             builder.buildItem(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                 &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;sphere_&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;i&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                 &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;sphere_base&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                 &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;sphere&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                 &lt;span style=&#34;color:#91d7e3&#34;&gt;Double&lt;/span&gt;.random(&lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt;: minX...maxX),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                 &lt;span style=&#34;color:#91d7e3&#34;&gt;Double&lt;/span&gt;.random(&lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt;: minY...maxY),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                 &lt;span style=&#34;color:#91d7e3&#34;&gt;Double&lt;/span&gt;.random(&lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt;: minZ...maxZ),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                 &lt;span style=&#34;color:#91d7e3&#34;&gt;Double&lt;/span&gt;.random(&lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt;: minRadius...maxRadius),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                 &lt;span style=&#34;color:#91d7e3&#34;&gt;Double&lt;/span&gt;.random(&lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt;: &lt;span style=&#34;color:#f5a97f&#34;&gt;0.&lt;/span&gt;..&lt;span style=&#34;color:#f5a97f&#34;&gt;1&lt;/span&gt;),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                 &lt;span style=&#34;color:#91d7e3&#34;&gt;Double&lt;/span&gt;.random(&lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt;: &lt;span style=&#34;color:#f5a97f&#34;&gt;0.&lt;/span&gt;..&lt;span style=&#34;color:#f5a97f&#34;&gt;1&lt;/span&gt;),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                 &lt;span style=&#34;color:#91d7e3&#34;&gt;Double&lt;/span&gt;.random(&lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt;: &lt;span style=&#34;color:#f5a97f&#34;&gt;0.&lt;/span&gt;..&lt;span style=&#34;color:#f5a97f&#34;&gt;1&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;             )
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;         }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;     }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; makeMultiBall(&lt;span style=&#34;color:#91d7e3&#34;&gt;count&lt;/span&gt;: &lt;span style=&#34;color:#91d7e3&#34;&gt;count&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;USDAFileBuilder&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    @StringBuilder &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;generateHeader&lt;/span&gt;(defaultPrim:&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;, metersPerUnit:&lt;span style=&#34;color:#91d7e3&#34;&gt;Double&lt;/span&gt; = &lt;span style=&#34;color:#f5a97f&#34;&gt;1&lt;/span&gt;, upAxis:&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt; = &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Y&amp;#34;&lt;/span&gt;, documentationNote:&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;? = &lt;span style=&#34;color:#f5a97f&#34;&gt;nil&lt;/span&gt;) -&amp;gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;#usda 1.0&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\n&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;(&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\t&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;defaultPrim = &lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;defaultPrim&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\t&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;metersPerUnit = &lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;metersPerUnit&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\t&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;upAxis = &lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;upAxis&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;documentationNote&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;doc = &lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;documentationNote&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;)&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;translateString&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; xoffset:&lt;span style=&#34;color:#91d7e3&#34;&gt;Double&lt;/span&gt;, &lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; yoffset:&lt;span style=&#34;color:#91d7e3&#34;&gt;Double&lt;/span&gt;, &lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; zoffset:&lt;span style=&#34;color:#91d7e3&#34;&gt;Double&lt;/span&gt;) -&amp;gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\t&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;double3 xformOp:translate = (&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;xoffset&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;, &lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;yoffset&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;, &lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;zoffset&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;)&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;opOrderStringTranslateOnly&lt;/span&gt;() -&amp;gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\t&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;uniform token[] xformOpOrder = [&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;xformOp:translate&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;]&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;colorString&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; red:&lt;span style=&#34;color:#91d7e3&#34;&gt;Double&lt;/span&gt;, &lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; green:&lt;span style=&#34;color:#91d7e3&#34;&gt;Double&lt;/span&gt;, &lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; blue:&lt;span style=&#34;color:#91d7e3&#34;&gt;Double&lt;/span&gt;) -&amp;gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\t\t&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;color3f[] primvars:displayColor = [(&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;red&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;, &lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;green&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;, &lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;blue&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;)]&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt;  &lt;span style=&#34;color:#8aadf4&#34;&gt;radiusString&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; radius:&lt;span style=&#34;color:#91d7e3&#34;&gt;Double&lt;/span&gt;) -&amp;gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\t\t&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;double radius = &lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;radius&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    @StringBuilder &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt;  &lt;span style=&#34;color:#8aadf4&#34;&gt;buildItem&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; id:&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;, &lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; reference_file:&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;, &lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; geometry_name:&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;, &lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; xoffset:&lt;span style=&#34;color:#91d7e3&#34;&gt;Double&lt;/span&gt;, &lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; yoffset:&lt;span style=&#34;color:#91d7e3&#34;&gt;Double&lt;/span&gt;, &lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; zoffset:&lt;span style=&#34;color:#91d7e3&#34;&gt;Double&lt;/span&gt;, &lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; radius:&lt;span style=&#34;color:#91d7e3&#34;&gt;Double&lt;/span&gt;, &lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; red:&lt;span style=&#34;color:#91d7e3&#34;&gt;Double&lt;/span&gt;, &lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; green:&lt;span style=&#34;color:#91d7e3&#34;&gt;Double&lt;/span&gt;, &lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; blue:&lt;span style=&#34;color:#91d7e3&#34;&gt;Double&lt;/span&gt;) -&amp;gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&amp;#34;&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;        &lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\n&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;over &amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;\&lt;/span&gt;(id)&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34; (&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\n\t&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;prepend references = @./&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;reference_file&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;.usd@&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\n&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\n&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;        &amp;#34;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; xoffset &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;!=&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;0&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;||&lt;/span&gt; yoffset &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;!=&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;0&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;||&lt;/span&gt; zoffset &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;!=&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;0&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            translateString(xoffset, yoffset, zoffset)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            opOrderStringTranslateOnly()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&amp;#34;&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;        &lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\t&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;over &amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;\&lt;/span&gt;(geometry_name)&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\n\t&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;        &amp;#34;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        colorString(red, green, blue)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        radiusString(radius)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\t&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;}&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;}&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    } 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;@resultBuilder
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;StringBuilder&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;buildBlock&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; parts: &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;...) -&amp;gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        parts.joined(separator: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\n&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;buildOptional&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; component:&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;?) -&amp;gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        component ?? &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;buildEither&lt;/span&gt;(&lt;span style=&#34;color:#91d7e3&#34;&gt;first&lt;/span&gt; component: &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;) -&amp;gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; component
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;buildEither&lt;/span&gt;(second component: &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;) -&amp;gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; component
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;buildArray&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; components: [&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;]) -&amp;gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        components.joined(separator: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\n&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;how-to-run&#34;&gt;How to run?&lt;/h2&gt;
&lt;p&gt;Oh the options now! From the project directory all of the following will work.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;swift run&lt;/code&gt; (multiball is the default command, with default options set)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;swift run sketchpad multiball -sc 4&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;swift run sketchpad multiball --help&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;swift run sketchpad multiball -o testFile.usd -c 32&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;No need to explicitly build. &lt;code&gt;swift run&lt;/code&gt; does that automatically. For more options don&amp;rsquo;t forget to:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-zsh&#34; data-lang=&#34;zsh&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;swift build --help
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;swift run --help 
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description>
    </item>
    
    
    
    <item>
      <title>Hello USD - Part 7: Where my error messages at????</title>
      <link>https://whynotestflight.com/excuses/hello-usd-part-7-where-my-error-messages-at/</link>
      <pubDate>Tue, 11 Jul 2023 00:00:00 +0000</pubDate>
      
      <guid>https://whynotestflight.com/excuses/hello-usd-part-7-where-my-error-messages-at/</guid>
      <description>&lt;p&gt;&lt;a href=&#34;https://whynotestflight.com/excuses/hello-usd-part-6-same-as-part-1...-but-swift/&#34;&gt;Yesterday&lt;/a&gt; my script outputted file(s) passed the Pixar Library&amp;rsquo;s &lt;code&gt;usdchecker&lt;/code&gt; but not the Apple&amp;rsquo;s USDZ Tools &lt;code&gt;usdARKitChecker&lt;/code&gt;. &lt;code&gt;usdARKitChecker&lt;/code&gt; was very coy about why.&lt;/p&gt;
&lt;p&gt;The TL:DR:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;usdchecker --arkit $FILENAME&lt;/code&gt; does a lot of what &lt;code&gt;usdARKitChecker&lt;/code&gt; does incase you don&amp;rsquo;t have that.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;usdcat -o $OUT_PUT_NAME.usdc --flatten $ROOT_SCENE_FILE.usda&lt;/code&gt; will smoosh all the usda files that &lt;code&gt;$ROOT_SCENE_FILE.usda&lt;/code&gt; sees into a single &lt;code&gt;.usdc&lt;/code&gt; file for ARKit compliance.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;System Info:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;MacOS 13.4 (Intel &amp;amp; Mac)&lt;/li&gt;
&lt;li&gt;VSCode 1.79.2 (Swift plugin from server working group  v1.4.0)&lt;/li&gt;
&lt;li&gt;swift-driver version: 1.75.2 Apple Swift version 5.8.1 (swiftlang-5.8.0.124.5 clang-1403.0.22.11.100)&lt;/li&gt;
&lt;li&gt;Pixar USD Library 23.05, (python 3.9.17 PySide 6.4.3)&lt;/li&gt;
&lt;li&gt;Added &lt;code&gt;**/__pycache__/&lt;/code&gt; to .gitignore&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;whats-in-the-apple-script&#34;&gt;What&amp;rsquo;s in the Apple script?&lt;/h2&gt;
&lt;p&gt;First thing I wanted to know was why the verbose mode &lt;code&gt;usdARKitChecker&lt;/code&gt; really wasn&amp;rsquo;t that chatty. No clarity of why my file failed. Also, since I&amp;rsquo;m new to so much of this I wanted a lot of feedback as to what was being checked and what could go wrong.&lt;/p&gt;
&lt;p&gt;So I went poking through the file.&lt;/p&gt;
&lt;p&gt;Code Apple&amp;rsquo;s (license in linked file later in post). Comments mine.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## should by python3? &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#!/usr/bin/python&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## Python libraries&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8bd5ca&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;subprocess&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;,&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;sys&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;,&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;os&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;,&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;argparse&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## pixar usd library python scripts&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8bd5ca&#34;&gt;from&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;pxr&lt;/span&gt; &lt;span style=&#34;color:#8bd5ca&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;*&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## validateMesh.py is file in same directory&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8bd5ca&#34;&gt;from&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;validateMesh&lt;/span&gt; &lt;span style=&#34;color:#8bd5ca&#34;&gt;import&lt;/span&gt; validateMesh
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## validateMaterial.py is file in same directory&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8bd5ca&#34;&gt;from&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;validateMaterial&lt;/span&gt; &lt;span style=&#34;color:#8bd5ca&#34;&gt;import&lt;/span&gt; validateMaterial
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## Note - these files are linked to later in post&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;validateFile&lt;/span&gt;(file, verbose, errorData):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## UsdStage &amp;#34;owns the scenegraph and provides access to a composition.&amp;#34; &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## https://github.com/PixarAnimationStudios/OpenUSD/blob/b53573ea2a6b29bc4a6b129f604bbb342c35df5c/pxr/usd/usd/stage.cpp#L866&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## https://openusd.org/release/api/usd_page_front.html&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    stage &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; Usd&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;.&lt;/span&gt;Stage&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;.&lt;/span&gt;Open(file)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## true until an error fires&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    success &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;True&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## https://github.com/PixarAnimationStudios/OpenUSD/blob/b53573ea2a6b29bc4a6b129f604bbb342c35df5c/pxr/usd/usd/primFlags.h#L576&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## https://github.com/PixarAnimationStudios/OpenUSD/blob/b53573ea2a6b29bc4a6b129f604bbb342c35df5c/pxr/usd/usd/primFlags.h#L135&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## Prims appear to have several booleans (flags) relating to their configuration / how deep they are, etc.  This &amp;#34;Usd_PrimFlagsPredicate&amp;#34; seems to gather them all together in a set and lets the summoner filter out non-relevant prims. (I suspect `Usd.PrimIsActive` etc are in fact bit masks as this really is a boolean and, not a logical and)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    predicate &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; Usd&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;.&lt;/span&gt;TraverseInstanceProxies(Usd&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;.&lt;/span&gt;PrimIsActive &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;amp;&lt;/span&gt; Usd&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;.&lt;/span&gt;PrimIsDefined &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;amp;&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;~&lt;/span&gt;Usd&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;.&lt;/span&gt;PrimIsAbstract)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;for&lt;/span&gt; prim &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;in&lt;/span&gt; stage&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;.&lt;/span&gt;Traverse(predicate):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; prim&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;.&lt;/span&gt;GetTypeName() &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;==&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Mesh&amp;#34;&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            success &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; validateMesh(prim, verbose, errorData) &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;and&lt;/span&gt; success
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; prim&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;.&lt;/span&gt;GetTypeName() &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;==&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Material&amp;#34;&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            success &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; validateMaterial(prim, verbose, errorData) &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;and&lt;/span&gt; success
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; success
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;runValidators&lt;/span&gt;(filename, verboseOutput, errorData):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## https://github.com/PixarAnimationStudios/OpenUSD/blob/b53573ea2a6b29bc4a6b129f604bbb342c35df5c/pxr/usd/usdUtils/complianceChecker.py#L912&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## RIGHT HERE THE ABOVE IS THE THING TO READ.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    checker &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; UsdUtils&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;.&lt;/span&gt;ComplianceChecker(arkit&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#f5a97f&#34;&gt;True&lt;/span&gt;, 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            skipARKitRootLayerCheck&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#f5a97f&#34;&gt;False&lt;/span&gt;, rootPackageOnly&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#f5a97f&#34;&gt;False&lt;/span&gt;, 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            skipVariants&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#f5a97f&#34;&gt;False&lt;/span&gt;, verbose&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#f5a97f&#34;&gt;False&lt;/span&gt;) &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## &amp;lt;-- Here is (a) verbose problem?&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# TODO: checker.DumpAllRules()?&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    checker&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;.&lt;/span&gt;CheckCompliance(filename)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    errors &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; checker&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;.&lt;/span&gt;GetErrors()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    failedChecks &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; checker&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;.&lt;/span&gt;GetFailedChecks()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;for&lt;/span&gt; rule &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;in&lt;/span&gt; checker&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;.&lt;/span&gt;_rules:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        error &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; rule&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;.&lt;/span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;__class__&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;.&lt;/span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;__name__&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        failures &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; rule&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;.&lt;/span&gt;GetFailedChecks()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;len&lt;/span&gt;(failures) &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;0&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            errorData&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;.&lt;/span&gt;append({ &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;code&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;PXR_&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;+&lt;/span&gt; error })
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            errors&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;.&lt;/span&gt;append(error)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    usdCheckerResult &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;len&lt;/span&gt;(errors) &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;==&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## Where are the errors being printed? &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## Do the custom checks from the other files&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## TODO: understand them&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    mdlValidation &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; validateFile(filename, verboseOutput, errorData)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    success &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; usdCheckerResult &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;and&lt;/span&gt; mdlValidation
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;usdARKitChecker: &amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;+&lt;/span&gt; (&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;[Pass]&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; success &lt;span style=&#34;color:#c6a0f6&#34;&gt;else&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;[Fail]&amp;#34;&lt;/span&gt;) &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;+&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34; &amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;+&lt;/span&gt; filename)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;main&lt;/span&gt;(argumentList, outErrorList&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#f5a97f&#34;&gt;None&lt;/span&gt;):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## Read in any arguments / options&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    parser &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; argparse&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;.&lt;/span&gt;ArgumentParser()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    parser&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;.&lt;/span&gt;add_argument(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;--verbose&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;-v&amp;#34;&lt;/span&gt;, action&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#39;store_true&amp;#39;&lt;/span&gt;, help&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Verbose mode.&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    parser&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;.&lt;/span&gt;add_argument(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#39;files&amp;#39;&lt;/span&gt;, nargs&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#39;*&amp;#39;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    args&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt;parser&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;.&lt;/span&gt;parse_args(argumentList)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    verboseOutput &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; args&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;.&lt;/span&gt;verbose
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## Validation succeeds until it fails. &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    totalSuccess &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;True&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;for&lt;/span&gt; filename &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;in&lt;/span&gt; args&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;.&lt;/span&gt;files:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        errorData &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; []
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## filename: from the loop&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## verboseOutput: From the flag&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## errorData: Just defined. &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        runValidators(filename, verboseOutput, errorData)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## outErrorList: defined in function call as None by default&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## When is it ever updated to not None? Is it just an optional out pipe? &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; outErrorList &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;is&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;not&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;None&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        	outErrorList&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;.&lt;/span&gt;append({ &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;file&amp;#34;&lt;/span&gt;: filename, &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;errors&amp;#34;&lt;/span&gt;: errorData })
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# We&amp;#39;re still good only if no new errors and no old errors&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        totalSuccess &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; totalSuccess &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;and&lt;/span&gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;len&lt;/span&gt;(errorData) &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;==&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## Program exits with no errors (code 0) if totalSuccess&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; totalSuccess:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;else&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;__name__&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;==&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#39;__main__&amp;#39;&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    argumentList &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; sys&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;.&lt;/span&gt;argv[&lt;span style=&#34;color:#f5a97f&#34;&gt;1&lt;/span&gt;:]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    sys&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;.&lt;/span&gt;exit(main(argumentList))
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;whats-in-the-pixar-script&#34;&gt;What&amp;rsquo;s in the Pixar script&lt;/h2&gt;
&lt;p&gt;An invaluable clue in the &lt;code&gt;usdARKitChecker&lt;/code&gt; script - how to find the Pixar script that drives &lt;code&gt;usdchecker&lt;/code&gt;, &lt;a href=&#34;https://github.com/PixarAnimationStudios/OpenUSD/blob/b53573ea2a6b29bc4a6b129f604bbb342c35df5c/pxr/usd/usdUtils/complianceChecker.py#L912&#34;&gt;&lt;code&gt;complianceChecker.py&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;So much information! I do not understand a lot of these terms yet, but I feel like I&amp;rsquo;m getting closer. Text copied from file linked to above:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Files within a usdz package must be laid out properly, i.e. they should be aligned to 64 bytes.&lt;/li&gt;
&lt;li&gt;Files within a usdz package should not be compressed or encrypted.&lt;/li&gt;
&lt;li&gt;The composed USD stage should not contain any unresolvable asset dependencies (in every possible variation of the asset), when using the default asset resolver. &amp;quot;&lt;/li&gt;
&lt;li&gt;All stages should declare their &amp;lsquo;upAxis&amp;rsquo; and &amp;lsquo;metersPerUnit&amp;rsquo;.&lt;br&gt;
Stages that can be consumed as referencable assets should furthermore have
a valid &amp;lsquo;defaultPrim&amp;rsquo; declared, and stages meant for consumer-level packaging
should always have upAxis set to &amp;lsquo;Y&amp;rsquo;&lt;/li&gt;
&lt;li&gt;Texture files should be readable by intended client (only .jpg, .jpeg or .png for consumer-level USDZ).
&lt;ul&gt;
&lt;li&gt;Supported Image Formats: (&amp;ldquo;jpg&amp;rdquo;, &amp;ldquo;jpeg&amp;rdquo;, &amp;ldquo;png&amp;rdquo;), special ARKit mode: (&amp;quot;.exr&amp;quot;)&lt;/li&gt;
&lt;li&gt;Unsupported Image Formats[&amp;ldquo;bmp&amp;rdquo;, &amp;ldquo;tga&amp;rdquo;, &amp;ldquo;hdr&amp;rdquo;, &amp;ldquo;exr&amp;rdquo;, &amp;ldquo;tif&amp;rdquo;, &amp;ldquo;zfile&amp;rdquo;, &amp;ldquo;tx&amp;rdquo;]&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Check for basic prim encapsulation rules:
&lt;ul&gt;
&lt;li&gt;Boundables may not be nested under Gprims&lt;/li&gt;
&lt;li&gt;Of course we must allow Boundables under other Boundables, so that schemas like UsdGeom.Pointinstancer can nest their prototypes.  But we disallow a PointInstancer under a Mesh just as we disallow a Mesh under a Mesh, for the same reason: we cannot then independently adjust visibility for the two objects, nor can we reasonably compute the parent Mesh&amp;rsquo;s extent.&lt;/li&gt;
&lt;li&gt;Connectable prims (e.g. Shader, Material, etc) can only be nested
inside other Container-like Connectable prims. Container-like prims
include Material, NodeGraph, Light, LightFilter, and &lt;em&gt;exclude Shader&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;UsdUVTexture nodes that feed the &lt;em&gt;inputs:normals&lt;/em&gt; of a
UsdPreviewSurface must ensure that the data is encoded and scaled properly.
Specifically:
&lt;ul&gt;
&lt;li&gt;Since normals are expected to be in the range [(-1,-1,-1), (1,1,1)],
the Texture node must transform 8-bit textures from their [0..1] range by
setting its &lt;em&gt;inputs:scale&lt;/em&gt; to (2, 2, 2, 1) and
&lt;em&gt;inputs:bias&lt;/em&gt; to (-1, -1, -1, 0)&lt;/li&gt;
&lt;li&gt;Normal map data is commonly expected to be linearly encoded.  However, many
image-writing tools automatically set the profile of three-channel, 8-bit
images to SRGB.  To prevent an unwanted transformation, the UsdUVTexture&amp;rsquo;s
&lt;em&gt;inputs:sourceColorSpace&lt;/em&gt; must be set to &amp;ldquo;raw&amp;rdquo;.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;A prim providing a material binding, must have MaterialBindingAPI applied on the prim.&lt;/li&gt;
&lt;li&gt;A prim providing skelBinding properties, must have SkelBindingAPI applied on the prim.&lt;/li&gt;
&lt;li&gt;ARKit Checker:
&lt;ul&gt;
&lt;li&gt;If the root layer is a package, then the composed stage should not contain references to files outside the package. In other words, the package should be entirely self-contained.&lt;/li&gt;
&lt;li&gt;Allowed Layer Formats: (&amp;lsquo;usd&amp;rsquo;, &amp;lsquo;usda&amp;rsquo;, &amp;lsquo;usdc&amp;rsquo;, &amp;lsquo;usdz&amp;rsquo;)&lt;/li&gt;
&lt;li&gt;_allowedPrimTypeNames = (&amp;rsquo;&amp;rsquo;, &amp;lsquo;Scope&amp;rsquo;, &amp;lsquo;Xform&amp;rsquo;, &amp;lsquo;Camera&amp;rsquo;, &amp;lsquo;Shader&amp;rsquo;, &amp;lsquo;Material&amp;rsquo;,&amp;lsquo;Mesh&amp;rsquo;, &amp;lsquo;Sphere&amp;rsquo;, &amp;lsquo;Cube&amp;rsquo;, &amp;lsquo;Cylinder&amp;rsquo;, &amp;lsquo;Cone&amp;rsquo;, &amp;lsquo;Capsule&amp;rsquo;, &amp;lsquo;GeomSubset&amp;rsquo;, &amp;lsquo;Points&amp;rsquo;, &amp;lsquo;SkelRoot&amp;rsquo;, &amp;lsquo;Skeleton&amp;rsquo;, &amp;lsquo;SkelAnimation&amp;rsquo;, &amp;lsquo;BlendShape&amp;rsquo;, &amp;lsquo;SpatialAudio&amp;rsquo;)&lt;/li&gt;
&lt;li&gt;UsdGeomPointInstancers and custom schemas not provided by core USD are not allowed.&lt;/li&gt;
&lt;li&gt;Shader nodes must have &amp;quot;id&amp;quot; as the implementationSource, with id values that begin with &amp;quot;Usd*&amp;quot;. Also, shader inputs with connections must each have a single, valid connection source.&lt;/li&gt;
&lt;li&gt;All material binding relationships must have valid targets.&lt;/li&gt;
&lt;li&gt;The root layer of the package must be a usdc file and must not include any external dependencies that participate in stage composition.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;getting-more-error-messages-out-usdarkitchecker&#34;&gt;Getting more error messages out &lt;code&gt;usdARKitChecker&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;Running&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-zsh&#34; data-lang=&#34;zsh&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;usdchecker --arkit ~/Developer/GitHub/USDHelloWorld/Part_06/multiball_20230709T222354.usda
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;supplies the following error:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;The stage uses 2 layers. It should contain a single usdc layer to be compatible with ARKit&amp;#39;s implementation of usdz. (fails &amp;#39;ARKitRootLayerChecker&amp;#39;)
Root layer of the stage &amp;#39;~/Developer/GitHub/USDHelloWorld/Part_06/multiball_20230709T222354.usda&amp;#39; does not have the &amp;#39;.usdc&amp;#39; extension. (fails &amp;#39;ARKitRootLayerChecker&amp;#39;)
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Why was I not getting that from &lt;code&gt;usdARKitChecker --verbose&lt;/code&gt;? Well now I am! ALL THE MESSAGES ALL THE TIME!!!&lt;/p&gt;
&lt;p&gt;Links to raw:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;usdARKitChecker_revised.py&#34;&gt;base script&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;validateMaterial.py&#34;&gt;validateMaterial&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;validateMesh.py&#34;&gt;validateMesh&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Also: &lt;a href=&#34;https://github.com/carlynorama/USDHelloWorld/tree/main/explorations/Part_07&#34;&gt;https://github.com/carlynorama/USDHelloWorld/tree/main/explorations/Part_07&lt;/a&gt;&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#5b6078;font-style:italic&#34;&gt;#!/usr/bin/python3&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## changed to python3&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8bd5ca&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;subprocess&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;,&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;sys&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;,&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;os&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;,&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;argparse&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8bd5ca&#34;&gt;from&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;pxr&lt;/span&gt; &lt;span style=&#34;color:#8bd5ca&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;*&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8bd5ca&#34;&gt;from&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;validateMesh&lt;/span&gt; &lt;span style=&#34;color:#8bd5ca&#34;&gt;import&lt;/span&gt; validateMesh
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8bd5ca&#34;&gt;from&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;validateMaterial&lt;/span&gt; &lt;span style=&#34;color:#8bd5ca&#34;&gt;import&lt;/span&gt; validateMaterial
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## No changes&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;validateFile&lt;/span&gt;(file, verbose, errorData):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    stage &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; Usd&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;.&lt;/span&gt;Stage&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;.&lt;/span&gt;Open(file)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    success &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;True&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    predicate &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; Usd&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;.&lt;/span&gt;TraverseInstanceProxies(Usd&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;.&lt;/span&gt;PrimIsActive &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;amp;&lt;/span&gt; Usd&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;.&lt;/span&gt;PrimIsDefined &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;amp;&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;~&lt;/span&gt;Usd&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;.&lt;/span&gt;PrimIsAbstract)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;for&lt;/span&gt; prim &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;in&lt;/span&gt; stage&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;.&lt;/span&gt;Traverse(predicate):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; prim&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;.&lt;/span&gt;GetTypeName() &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;==&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Mesh&amp;#34;&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            success &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; validateMesh(prim, verbose, errorData) &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;and&lt;/span&gt; success
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; prim&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;.&lt;/span&gt;GetTypeName() &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;==&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Material&amp;#34;&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            success &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; validateMaterial(prim, verbose, errorData) &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;and&lt;/span&gt; success
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; success
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## More verbose verbose mode&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;runValidators&lt;/span&gt;(filename, verboseOutput, errorData):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    checker &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; UsdUtils&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;.&lt;/span&gt;ComplianceChecker(arkit&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#f5a97f&#34;&gt;True&lt;/span&gt;, 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            skipARKitRootLayerCheck&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#f5a97f&#34;&gt;False&lt;/span&gt;, rootPackageOnly&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#f5a97f&#34;&gt;False&lt;/span&gt;, 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            skipVariants&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#f5a97f&#34;&gt;False&lt;/span&gt;, verbose&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt;verboseOutput) &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#&amp;lt;- changed to pass verboseOutput through&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    checker&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;.&lt;/span&gt;CheckCompliance(filename)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; verboseOutput:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Rules Being Checked by usdchecker:&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# checker.DumpAllRules() line failed with error: &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# for ruleNum, rule in enumerate(GetBaseRules()):   &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# NameError: name &amp;#39;GetBaseRules&amp;#39; is not defined&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;for&lt;/span&gt; rule &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;in&lt;/span&gt; checker&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;.&lt;/span&gt;_rules:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(rule)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;-----&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    errors &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; checker&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;.&lt;/span&gt;GetErrors()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    failedChecks &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; checker&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;.&lt;/span&gt;GetFailedChecks()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    warnings &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; checker&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;.&lt;/span&gt;GetWarnings()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; verboseOutput:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;for&lt;/span&gt; warning &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;in&lt;/span&gt; warnings:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(warning)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;for&lt;/span&gt; error &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;in&lt;/span&gt; errors:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(error)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;for&lt;/span&gt; failure &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;in&lt;/span&gt; failedChecks:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(failure)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;-----&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;for&lt;/span&gt; rule &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;in&lt;/span&gt; checker&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;.&lt;/span&gt;_rules:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        error &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; rule&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;.&lt;/span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;__class__&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;.&lt;/span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;__name__&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        failures &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; rule&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;.&lt;/span&gt;GetFailedChecks()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;len&lt;/span&gt;(failures) &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;0&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            errorData&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;.&lt;/span&gt;append({ &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;code&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;PXR_&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;+&lt;/span&gt; error })
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            errors&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;.&lt;/span&gt;append(error)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; verboseOutput:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Will be exported to outErrorList&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(errorData)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;----&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    usdCheckerResult &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;len&lt;/span&gt;(errors) &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;==&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    mdlValidation &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; validateFile(filename, verboseOutput, errorData)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    success &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; usdCheckerResult &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;and&lt;/span&gt; mdlValidation
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;usdARKitChecker: &amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;+&lt;/span&gt; (&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;[Pass]&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; success &lt;span style=&#34;color:#c6a0f6&#34;&gt;else&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;[Fail]&amp;#34;&lt;/span&gt;) &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;+&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34; &amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;+&lt;/span&gt; filename)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## No changes&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;main&lt;/span&gt;(argumentList, outErrorList&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#f5a97f&#34;&gt;None&lt;/span&gt;):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    parser &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; argparse&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;.&lt;/span&gt;ArgumentParser()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    parser&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;.&lt;/span&gt;add_argument(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;--verbose&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;-v&amp;#34;&lt;/span&gt;, action&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#39;store_true&amp;#39;&lt;/span&gt;, help&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Verbose mode.&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    parser&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;.&lt;/span&gt;add_argument(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#39;files&amp;#39;&lt;/span&gt;, nargs&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#39;*&amp;#39;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    args&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt;parser&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;.&lt;/span&gt;parse_args(argumentList)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    verboseOutput &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; args&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;.&lt;/span&gt;verbose
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    totalSuccess &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;True&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;for&lt;/span&gt; filename &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;in&lt;/span&gt; args&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;.&lt;/span&gt;files:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        errorData &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; []
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        runValidators(filename, verboseOutput, errorData)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; outErrorList &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;is&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;not&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;None&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            outErrorList&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;.&lt;/span&gt;append({ &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;file&amp;#34;&lt;/span&gt;: filename, &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;errors&amp;#34;&lt;/span&gt;: errorData })
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        totalSuccess &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; totalSuccess &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;and&lt;/span&gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;len&lt;/span&gt;(errorData) &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;==&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; totalSuccess:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;else&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;__name__&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;==&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#39;__main__&amp;#39;&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    argumentList &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; sys&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;.&lt;/span&gt;argv[&lt;span style=&#34;color:#f5a97f&#34;&gt;1&lt;/span&gt;:]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    sys&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;.&lt;/span&gt;exit(main(argumentList))
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;why-use-usdarkitchecker-at-all&#34;&gt;Why use &lt;code&gt;usdARKitChecker&lt;/code&gt; at all?&lt;/h2&gt;
&lt;p&gt;Unclear to me, someone new to the party, what hasn&amp;rsquo;t been ported to the Pixar library yet. I haven&amp;rsquo;t tested anything with materials or meshes and I don&amp;rsquo;t know if the extra files provided in the USDZ Tools still give a needed extra layer. They seem to check models fairly extensively. But cross referencing &lt;code&gt;usdchecker&lt;/code&gt; on some of the terms seems to reflect the scripts are feeling around similar areas in some cases. ALSO haven&amp;rsquo;t even begun to poke at &lt;code&gt;ARKit&lt;/code&gt;, &lt;code&gt;ModelIO&lt;/code&gt;, the new betas, etc to see what tools are baked in to the frameworks that might be more on the beaten path.&lt;/p&gt;
&lt;h2 id=&#34;can-i-fix-my-scripts-compliance&#34;&gt;Can I fix my scripts compliance?&lt;/h2&gt;
&lt;p&gt;My problems with making my files ARKit compliant are both easier and harder to fix than I was hoping.&lt;/p&gt;
&lt;p&gt;Easier in that I can still use primitives and don&amp;rsquo;t need to make a Scene, the problems I thought I was having. Switching over to a meshes and embedding things into scenes or creating assemblies would have been new territory.&lt;/p&gt;
&lt;p&gt;Harder because I am not going to be writing a Swift USDA -&amp;gt; USDC compressor algorithm anytime in the near future and if I want to embed a .usda generator in a project that will punt it to ARKit I don&amp;rsquo;t know how to do that yet and now it seems without usdc, there will be no joy. I&amp;rsquo;d like to do a demo project of getting a Swift wrapper around C++, but the OpenUSD Pixar tools have a lot going on.&lt;/p&gt;
&lt;p&gt;In the mean time I will live with a little post processing.&lt;/p&gt;
&lt;p&gt;My first successful attempt at force-fixing my files was:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-zsh&#34; data-lang=&#34;zsh&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;usdview ../Part_06/multiball_20230709T222354.usda
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# File &amp;gt; Save flattened as... (choose USDC option)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;usdchecker --arkit multiball_20230709T222354_flattened.usdc
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;gt; Success!
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;python3 usdARKitChecker_revised.py multiball_20230709T222354_flattened.usdc
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;gt; usdARKitChecker: &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;[&lt;/span&gt;Pass&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;]&lt;/span&gt; multiball_20230709T222354_flattened.usdc
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This requires actual interaction from a human, so not tenable in the long run.&lt;/p&gt;
&lt;p&gt;Second successful attempt:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-zsh&#34; data-lang=&#34;zsh&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# note just the ONE input file name, the root scene file&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;usdcat -o output_test_2.usdc --flatten ../Part_06/multiball_20230709T222354.usda
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;python3 usdARKitChecker_revised.py output_test_2.usdc
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;gt; usdARKitChecker: &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;[&lt;/span&gt;Pass&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;]&lt;/span&gt; output_test_2.usdc
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;See.. its a USDC now!&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;its_a_usdc.png&#34; alt=&#34;Group of 13 spheres, all different colors. Kind of looks like the picture from yesterday.&#34;&gt;&lt;/p&gt;
&lt;p&gt;Size savings: (5KB + 415 bytes) for uncompressed 3KB for compressed.&lt;/p&gt;
&lt;p&gt;Failed attempts involved:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;using &lt;code&gt;usdzip&lt;/code&gt; right away (still fails because the zipped up files were still more than 1 file, and not usdc)&lt;/li&gt;
&lt;li&gt;trying to use &lt;code&gt;usdcat&lt;/code&gt; to flat AND convert at the same time while giving it all the files associated with my scene instead of just the root file.&lt;/li&gt;
&lt;li&gt;trying &lt;code&gt;python3 /Applications/usdpython/usdzconvert/usdzconvert ../Part_06/multiball_20230709T222354.usda&lt;/code&gt; is interesting. Right at the top there was a warning about an unflattened file, but then the script just brazened it&amp;rsquo;s way through with tons of warnings, creating a .usdz file that passed the ARKit validation check but contained nothing to load. The script&amp;rsquo;s behavior reflects the correct &amp;ldquo;do your best&amp;rdquo; failure mode, I think, for a complex file where some assets might be available and some not, but kind of amusing in this simple case. I do not yet understand what &amp;ldquo;composition arcs&amp;rdquo; do.
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;Warning: in UsdUtilsCreateNewARKitUsdzPackage at line 1329 of $USDREPO/pxr/usd/usdUtils/dependencies.cpp -- The given asset &#39;/var/folders/qb/g6s3spx57x7f0nbrt3_613nh0000gn/T/tmpri1etvnvusdzconvert/multiball_20230709T222354.usdc&#39; contains one or more composition arcs referencing external USD files. Flattening it to a single .usdc file before packaging. This will result in loss of features such as variantSets and all asset references to be absolutized.&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Before I found the right order / combination of &lt;code&gt;usdcat&lt;/code&gt; parameters I started to write a shell script. It works, but I leave it here only for the record since the one liner is better.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-sh&#34; data-lang=&#34;sh&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#!/bin/sh
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# Usage: give the script the name of the root file and&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# the root file only, not the full list. &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# can be replaced with &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# `usdcat -o $OUTPUT_NAME --flatten $INPUT_ROOT_FILE``&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#PATH_TO_USDCAT=&amp;#34;somepath&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;REMOVE_TMP_FLAG&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#91d7e3&#34;&gt;false&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;TMP_FILE_NAME&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;smash_tmp.usda&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;OUTPUT_NAME&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;smash_output.usdc&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# using $@ (all args) is iffy here since really&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# should be passing _one_ file name after all.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;usdcat --flatten &lt;span style=&#34;color:#f4dbd6&#34;&gt;$@&lt;/span&gt; &amp;gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;$TMP_FILE_NAME&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;usdcat -o &lt;span style=&#34;color:#f4dbd6&#34;&gt;$OUTPUT_NAME&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;$TMP_FILE_NAME&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;$REMOVE_TMP_FLAG&lt;/span&gt;; &lt;span style=&#34;color:#c6a0f6&#34;&gt;then&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    rm &lt;span style=&#34;color:#f4dbd6&#34;&gt;$TMP_FILE_NAME&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;fi&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description>
    </item>
    
    
    
    <item>
      <title>Hello USD - Part 6: Same as Part 1... but Swift</title>
      <link>https://whynotestflight.com/excuses/hello-usd-part-6-same-as-part-1...-but-swift/</link>
      <pubDate>Mon, 10 Jul 2023 00:00:00 +0000</pubDate>
      
      <guid>https://whynotestflight.com/excuses/hello-usd-part-6-same-as-part-1...-but-swift/</guid>
      <description>&lt;ul&gt;
&lt;li&gt;MacOS 13.4 (Intel &amp;amp; Mac)&lt;/li&gt;
&lt;li&gt;VSCode 1.79.2 (Swift plugin from server working group  v1.4.0)&lt;/li&gt;
&lt;li&gt;swift-driver version: 1.75.2 Apple Swift version 5.8.1 (swiftlang-5.8.0.124.5 clang-1403.0.22.11.100)&lt;/li&gt;
&lt;li&gt;Pixar USD Library 23.05, (python 3.9.17 PySide 6.4.3)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Back from vacation and raring&amp;hellip; to do what I just did about a week ago! Well, to do it with Swift and some handy validation tools.&lt;/p&gt;
&lt;h2 id=&#34;making-the-file&#34;&gt;Making the File&lt;/h2&gt;
&lt;p&gt;Back in February I looked into doing &lt;a href=&#34;https://whynotestflight.com/excuses/getting-scripty/&#34;&gt;scripting in Swift&lt;/a&gt; as bare bones as possible (No ArgumentParser, no package).&lt;/p&gt;
&lt;p&gt;Building on that, I compiled a multi-file example with &lt;code&gt;swiftc *swift -o multiball&lt;/code&gt; in the directory with the following collection of &lt;code&gt;.swift&lt;/code&gt; files. (&lt;code&gt;./multiball&lt;/code&gt; to run.)&lt;/p&gt;
&lt;p&gt;Not a lot of new territory here, these Swift files recreate the approach from the Python file in &lt;a href=&#34;https://whynotestflight.com/excuses/ooohh-a-new-file-format...-hello-usd-part-1/&#34;&gt;part one&lt;/a&gt; with two structural differences:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;the added convenience of a &lt;code&gt;@resultBuilder&lt;/code&gt; called &lt;code&gt;StringBuilder&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;the string creating functions live in their own strut called &lt;code&gt;USDFileBuilder&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;mainswift&#34;&gt;main.swift&lt;/h3&gt;
&lt;p&gt;The code entry point is an explicitly named &lt;code&gt;main.swift&lt;/code&gt; file.&lt;/p&gt;
&lt;p&gt;NOTE: If there is no file called &lt;code&gt;main.swift&lt;/code&gt;, there must be something else telling the compiler where to start. In the &lt;a href=&#34;https://github.com/carlynorama/APIng/&#34;&gt;APIng package&lt;/a&gt;, for example, the &lt;code&gt;struct&lt;/code&gt; &lt;code&gt;APIng&lt;/code&gt; has the label &lt;code&gt;@main&lt;/code&gt; and a function &lt;code&gt;main()&lt;/code&gt; This level of control was added in &lt;a href=&#34;https://github.com/apple/swift-evolution/blob/main/proposals/0281-main-attribute.md&#34;&gt;Swift 5.3&lt;/a&gt; (For history see 2014 Apple dev post &lt;a href=&#34;https://developer.apple.com/swift/blog/?id=7&#34;&gt;Files and Initialization&lt;/a&gt;)&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;Foundation&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;minX&lt;/span&gt; = &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;-&lt;/span&gt;&lt;span style=&#34;color:#f5a97f&#34;&gt;4.0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;maxX&lt;/span&gt; = &lt;span style=&#34;color:#f5a97f&#34;&gt;4.0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;minY&lt;/span&gt; = minX
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;maxY&lt;/span&gt; = maxX
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;minZ&lt;/span&gt; = minX
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;maxZ&lt;/span&gt; = maxX
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;minRadius&lt;/span&gt; = &lt;span style=&#34;color:#f5a97f&#34;&gt;0.8&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;maxRadius&lt;/span&gt; = &lt;span style=&#34;color:#f5a97f&#34;&gt;2.0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;timeStampForFile&lt;/span&gt;() -&amp;gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//Date.now.ISO8601Format()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;date&lt;/span&gt; = Date.now
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;formatter&lt;/span&gt; = DateFormatter()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    formatter.dateFormat = &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;yyyyMMdd&amp;#39;T&amp;#39;HHmmss&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; formatter.string(from: date)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;@StringBuilder &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt;  &lt;span style=&#34;color:#8aadf4&#34;&gt;makeMultiBall&lt;/span&gt;(&lt;span style=&#34;color:#91d7e3&#34;&gt;count&lt;/span&gt;:&lt;span style=&#34;color:#91d7e3&#34;&gt;Int&lt;/span&gt;) -&amp;gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;builder&lt;/span&gt; = USDAFileBuilder()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    builder.generateHeader(defaultPrim:&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;blueSphere&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    builder.buildItem(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;blueSphere&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;sphere_base&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;sphere&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#f5a97f&#34;&gt;0&lt;/span&gt;, &lt;span style=&#34;color:#f5a97f&#34;&gt;0&lt;/span&gt;, &lt;span style=&#34;color:#f5a97f&#34;&gt;0&lt;/span&gt;, &lt;span style=&#34;color:#f5a97f&#34;&gt;1&lt;/span&gt;, &lt;span style=&#34;color:#f5a97f&#34;&gt;0&lt;/span&gt;, &lt;span style=&#34;color:#f5a97f&#34;&gt;0&lt;/span&gt;, &lt;span style=&#34;color:#f5a97f&#34;&gt;1&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;for&lt;/span&gt; i &lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt; (&lt;span style=&#34;color:#f5a97f&#34;&gt;0.&lt;/span&gt;..&lt;span style=&#34;color:#91d7e3&#34;&gt;count&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        builder.buildItem(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;sphere_&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;i&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;, 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;sphere_base&amp;#34;&lt;/span&gt;, 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;sphere&amp;#34;&lt;/span&gt;, 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#91d7e3&#34;&gt;Double&lt;/span&gt;.random(&lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt;: minX...maxX), 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#91d7e3&#34;&gt;Double&lt;/span&gt;.random(&lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt;: minY...maxY), 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#91d7e3&#34;&gt;Double&lt;/span&gt;.random(&lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt;: minZ...maxZ), 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#91d7e3&#34;&gt;Double&lt;/span&gt;.random(&lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt;: minRadius...maxRadius), 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#91d7e3&#34;&gt;Double&lt;/span&gt;.random(&lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt;: &lt;span style=&#34;color:#f5a97f&#34;&gt;0.&lt;/span&gt;..&lt;span style=&#34;color:#f5a97f&#34;&gt;1&lt;/span&gt;), 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#91d7e3&#34;&gt;Double&lt;/span&gt;.random(&lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt;: &lt;span style=&#34;color:#f5a97f&#34;&gt;0.&lt;/span&gt;..&lt;span style=&#34;color:#f5a97f&#34;&gt;1&lt;/span&gt;), 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#91d7e3&#34;&gt;Double&lt;/span&gt;.random(&lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt;: &lt;span style=&#34;color:#f5a97f&#34;&gt;0.&lt;/span&gt;..&lt;span style=&#34;color:#f5a97f&#34;&gt;1&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        )
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;inputArgs&lt;/span&gt; = CommandLine.arguments.&lt;span style=&#34;color:#91d7e3&#34;&gt;dropFirst&lt;/span&gt;()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Number of arguments:&amp;#34;&lt;/span&gt;, inputArgs.&lt;span style=&#34;color:#91d7e3&#34;&gt;count&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;count&lt;/span&gt;:&lt;span style=&#34;color:#91d7e3&#34;&gt;Int&lt;/span&gt; = &lt;span style=&#34;color:#f5a97f&#34;&gt;12&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;fileName&lt;/span&gt;:&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt; = &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;multiball_&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;timeStampForFile&lt;span style=&#34;color:#a6da95&#34;&gt;())&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;.usda&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;switch&lt;/span&gt; (inputArgs.&lt;span style=&#34;color:#91d7e3&#34;&gt;count&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;case&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;1&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;guard&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;tmp_count&lt;/span&gt; = &lt;span style=&#34;color:#91d7e3&#34;&gt;Int&lt;/span&gt;(inputArgs[&lt;span style=&#34;color:#f5a97f&#34;&gt;0&lt;/span&gt;]) &lt;span style=&#34;color:#c6a0f6&#34;&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#91d7e3&#34;&gt;fatalError&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Argument is not a number so can&amp;#39;t create a count&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#91d7e3&#34;&gt;count&lt;/span&gt; = tmp_count
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;case&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;2&lt;/span&gt;: 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;guard&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;tmp_count&lt;/span&gt; = &lt;span style=&#34;color:#91d7e3&#34;&gt;Int&lt;/span&gt;(inputArgs[&lt;span style=&#34;color:#f5a97f&#34;&gt;0&lt;/span&gt;]) &lt;span style=&#34;color:#c6a0f6&#34;&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#91d7e3&#34;&gt;fatalError&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Argument is not a number so can&amp;#39;t create a count&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        fileName = inputArgs[&lt;span style=&#34;color:#f5a97f&#34;&gt;1&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#91d7e3&#34;&gt;count&lt;/span&gt; = tmp_count
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;default&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Undecipherable number of arguments. Using defaults.&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;&lt;span style=&#34;color:#91d7e3&#34;&gt;count&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;, &lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;fileName&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;usdFileText&lt;/span&gt; = makeMultiBall(&lt;span style=&#34;color:#91d7e3&#34;&gt;count&lt;/span&gt;: &lt;span style=&#34;color:#91d7e3&#34;&gt;count&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;fileURL&lt;/span&gt; = URL(filePath: fileName)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;do&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; usdFileText.write(to: fileURL, atomically: &lt;span style=&#34;color:#f5a97f&#34;&gt;true&lt;/span&gt;, encoding: &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;.Encoding.utf8)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;} &lt;span style=&#34;color:#c6a0f6&#34;&gt;catch&lt;/span&gt; { 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(error)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;stringbuilderswift&#34;&gt;StringBuilder.swift&lt;/h3&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;Foundation&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;@resultBuilder
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;StringBuilder&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;buildBlock&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; parts: &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;...) -&amp;gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        parts.joined(separator: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\n&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;buildOptional&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; component:&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;?) -&amp;gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        component ?? &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;buildEither&lt;/span&gt;(&lt;span style=&#34;color:#91d7e3&#34;&gt;first&lt;/span&gt; component: &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;) -&amp;gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; component
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;buildEither&lt;/span&gt;(second component: &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;) -&amp;gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; component
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;buildArray&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; components: [&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;]) -&amp;gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        components.joined(separator: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\n&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h4 id=&#34;resources&#34;&gt;Resources&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://www.hackingwithswift.com/swift/5.4/result-builders&#34;&gt;https://www.hackingwithswift.com/swift/5.4/result-builders&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/apple/swift-evolution/blob/main/proposals/0289-result-builders.md&#34;&gt;https://github.com/apple/swift-evolution/blob/main/proposals/0289-result-builders.md&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;usdafilebuilderswift&#34;&gt;USDAFileBuilder.swift&lt;/h3&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;USDAFileBuilder&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;@StringBuilder &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;generateHeader&lt;/span&gt;(defaultPrim:&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;, metersPerUnit:&lt;span style=&#34;color:#91d7e3&#34;&gt;Double&lt;/span&gt; = &lt;span style=&#34;color:#f5a97f&#34;&gt;1&lt;/span&gt;, upAxis:&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt; = &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Y&amp;#34;&lt;/span&gt;, documentationNote:&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;? = &lt;span style=&#34;color:#f5a97f&#34;&gt;nil&lt;/span&gt;) -&amp;gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;#usda 1.0&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\n&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;(&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\t&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;defaultPrim = &lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;defaultPrim&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\t&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;metersPerUnit = &lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;metersPerUnit&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\t&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;upAxis = &lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;upAxis&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;documentationNote&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;doc = &lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;documentationNote&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;)&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;translateString&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; xoffset:&lt;span style=&#34;color:#91d7e3&#34;&gt;Double&lt;/span&gt;, &lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; yoffset:&lt;span style=&#34;color:#91d7e3&#34;&gt;Double&lt;/span&gt;, &lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; zoffset:&lt;span style=&#34;color:#91d7e3&#34;&gt;Double&lt;/span&gt;) -&amp;gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\t&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;double3 xformOp:translate = (&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;xoffset&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;, &lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;yoffset&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;, &lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;zoffset&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;)&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;opOrderStringTranslateOnly&lt;/span&gt;() -&amp;gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\t&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;uniform token[] xformOpOrder = [&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;xformOp:translate&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;]&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;colorString&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; red:&lt;span style=&#34;color:#91d7e3&#34;&gt;Double&lt;/span&gt;, &lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; green:&lt;span style=&#34;color:#91d7e3&#34;&gt;Double&lt;/span&gt;, &lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; blue:&lt;span style=&#34;color:#91d7e3&#34;&gt;Double&lt;/span&gt;) -&amp;gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\t\t&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;color3f[] primvars:displayColor = [(&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;red&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;, &lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;green&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;, &lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;blue&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;)]&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt;  &lt;span style=&#34;color:#8aadf4&#34;&gt;radiusString&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; radius:&lt;span style=&#34;color:#91d7e3&#34;&gt;Double&lt;/span&gt;) -&amp;gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;     &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\t\t&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;double radius = &lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;radius&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;@StringBuilder &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt;  &lt;span style=&#34;color:#8aadf4&#34;&gt;buildItem&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; id:&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;, &lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; reference_file:&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;, &lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; geometry_name:&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;, &lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; xoffset:&lt;span style=&#34;color:#91d7e3&#34;&gt;Double&lt;/span&gt;, &lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; yoffset:&lt;span style=&#34;color:#91d7e3&#34;&gt;Double&lt;/span&gt;, &lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; zoffset:&lt;span style=&#34;color:#91d7e3&#34;&gt;Double&lt;/span&gt;, &lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; radius:&lt;span style=&#34;color:#91d7e3&#34;&gt;Double&lt;/span&gt;, &lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; red:&lt;span style=&#34;color:#91d7e3&#34;&gt;Double&lt;/span&gt;, &lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; green:&lt;span style=&#34;color:#91d7e3&#34;&gt;Double&lt;/span&gt;, &lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; blue:&lt;span style=&#34;color:#91d7e3&#34;&gt;Double&lt;/span&gt;) -&amp;gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&amp;#34;&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;    &lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\n&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;over &amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;\&lt;/span&gt;(id)&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34; (&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\n\t&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;prepend references = @./&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;reference_file&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;.usd@&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\n&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\n&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;    &amp;#34;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; xoffset &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;!=&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;0&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;||&lt;/span&gt; yoffset &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;!=&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;0&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;||&lt;/span&gt; zoffset &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;!=&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;0&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        translateString(xoffset, yoffset, zoffset)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        opOrderStringTranslateOnly()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;               
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&amp;#34;&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;    &lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\t&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;over &amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;\&lt;/span&gt;(geometry_name)&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\n\t&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;    &amp;#34;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    colorString(red, green, blue)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    radiusString(radius)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\t&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;}&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;}&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;} 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;validating-the-file&#34;&gt;Validating the File&lt;/h2&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-sh&#34; data-lang=&#34;sh&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# pwd folder with files to check. &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# shell session launched with .command file / working build in path&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;usdchecker sphere_base.usd
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;usdchecker multiball.usda
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The Pixar USD library comes with a &lt;code&gt;usdchecker&lt;/code&gt; utility that, when pointed at the original output of &lt;a href=&#34;https://whynotestflight.com/excuses/ooohh-a-new-file-format...-hello-usd-part-1/&#34;&gt;Part 01&lt;/a&gt;&amp;rsquo;s &lt;code&gt;multiball_20230627T132245.usd&lt;/code&gt; file, spits out some errors:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;Stage does not specify an upAxis. (fails &amp;#39;StageMetadataChecker&amp;#39;)
Stage does not specify its linear scale in metersPerUnit. (fails &amp;#39;StageMetadataChecker&amp;#39;)
Stage has missing or invalid defaultPrim. (fails &amp;#39;StageMetadataChecker&amp;#39;)
Failed!
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The &lt;code&gt;generateHeader&lt;/code&gt; function fixes those problems in the new files by adding the needed meta data.&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-usd&#34; data-lang=&#34;usd&#34;&gt;#usda 1.0
(
	defaultPrim = &amp;#34;blueSphere&amp;#34;
	metersPerUnit = 1.0
	upAxis = &amp;#34;Y&amp;#34;
)
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Other fixes will be necessary because choosing the origin marker &amp;ldquo;blueSphere&amp;rdquo; as the &lt;code&gt;defaultPrim&lt;/code&gt; doesn&amp;rsquo;t exactly fit conceptually with the spheres acting as an assemblage.  I&amp;rsquo;m wondering if creating scene or an assemblage will also fix the USDZ Tools &lt;code&gt;usdARKitChecker&lt;/code&gt; failure. This script may or may not jibe with what the latest ARKit imports can do, but I still may try to get a passing check.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-zsh&#34; data-lang=&#34;zsh&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# Python3 here referes to 3.9.17, against fresh build &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# of Pixar tools. NOT the included USDZ Tools build&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;$ python3 /Applications/usdpython/usdzconvert/usdARKitChecker -v multiball_20230709T222354.usda
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# If that&amp;#39;s verbose...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;gt; usdARKitChecker: &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;[&lt;/span&gt;Fail&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;]&lt;/span&gt; multiball_20230709T222354.usda
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;For now though it works!&lt;/p&gt;
&lt;h2 id=&#34;full-output-file&#34;&gt;Full Output File&lt;/h2&gt;
&lt;p&gt;&lt;img src=&#34;swift_generated_multiball.png&#34; alt=&#34;INSERT DESCRIPTIOn&#34;&gt;&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-usd&#34; data-lang=&#34;usd&#34;&gt;#usda 1.0
(
	defaultPrim = &amp;#34;blueSphere&amp;#34;
	metersPerUnit = 1.0
	upAxis = &amp;#34;Y&amp;#34;

)

over &amp;#34;blueSphere&amp;#34; (
	prepend references = @./sphere_base.usd@
)
{

	over &amp;#34;sphere&amp;#34;
	{
		color3f[] primvars:displayColor = [(0.0, 0.0, 1.0)]
		double radius = 1.0
	}
}

over &amp;#34;sphere_0&amp;#34; (
	prepend references = @./sphere_base.usd@
)
{
	double3 xformOp:translate = (-1.184153285968514, -3.647033671109095, -3.7641420584021335)
	uniform token[] xformOpOrder = [&amp;#34;xformOp:translate&amp;#34;]
	over &amp;#34;sphere&amp;#34;
	{
		color3f[] primvars:displayColor = [(0.16205418618238365, 0.5734559688991189, 0.38217704094058846)]
		double radius = 1.4002723309372764
	}
}

over &amp;#34;sphere_1&amp;#34; (
	prepend references = @./sphere_base.usd@
)
{
	double3 xformOp:translate = (-0.5261383868331437, 3.132048637184454, -0.44706351337151684)
	uniform token[] xformOpOrder = [&amp;#34;xformOp:translate&amp;#34;]
	over &amp;#34;sphere&amp;#34;
	{
		color3f[] primvars:displayColor = [(0.7178610937878546, 0.2673176415923212, 0.27736339801237053)]
		double radius = 1.6608855195133203
	}
}

over &amp;#34;sphere_2&amp;#34; (
	prepend references = @./sphere_base.usd@
)
{
	double3 xformOp:translate = (2.696991757170985, -2.741134838471454, 2.2709444095213973)
	uniform token[] xformOpOrder = [&amp;#34;xformOp:translate&amp;#34;]
	over &amp;#34;sphere&amp;#34;
	{
		color3f[] primvars:displayColor = [(0.9498042527272043, 0.9570184832609097, 0.7820600053071775)]
		double radius = 1.7846037873381584
	}
}

over &amp;#34;sphere_3&amp;#34; (
	prepend references = @./sphere_base.usd@
)
{
	double3 xformOp:translate = (-1.0308012065228462, 0.45496116972412803, 2.1602285177573757)
	uniform token[] xformOpOrder = [&amp;#34;xformOp:translate&amp;#34;]
	over &amp;#34;sphere&amp;#34;
	{
		color3f[] primvars:displayColor = [(0.7291305159904483, 0.07002904075700511, 0.7767305210318993)]
		double radius = 1.697103659651786
	}
}

over &amp;#34;sphere_4&amp;#34; (
	prepend references = @./sphere_base.usd@
)
{
	double3 xformOp:translate = (1.083654492166584, 3.495198151700426, 3.001139568538912)
	uniform token[] xformOpOrder = [&amp;#34;xformOp:translate&amp;#34;]
	over &amp;#34;sphere&amp;#34;
	{
		color3f[] primvars:displayColor = [(0.19330187806556043, 0.5521787997886198, 0.6234825293272558)]
		double radius = 1.9267084402944623
	}
}

over &amp;#34;sphere_5&amp;#34; (
	prepend references = @./sphere_base.usd@
)
{
	double3 xformOp:translate = (-0.7130466964579423, -1.6967393634184456, -2.8650597646849745)
	uniform token[] xformOpOrder = [&amp;#34;xformOp:translate&amp;#34;]
	over &amp;#34;sphere&amp;#34;
	{
		color3f[] primvars:displayColor = [(0.40969230788788025, 0.3848698971870308, 0.38478111434269124)]
		double radius = 1.5136302027051698
	}
}

over &amp;#34;sphere_6&amp;#34; (
	prepend references = @./sphere_base.usd@
)
{
	double3 xformOp:translate = (2.114100481739248, -1.2331921314814318, 2.9210878637892135)
	uniform token[] xformOpOrder = [&amp;#34;xformOp:translate&amp;#34;]
	over &amp;#34;sphere&amp;#34;
	{
		color3f[] primvars:displayColor = [(0.42377170754294957, 0.8944820544786956, 0.8387197785634217)]
		double radius = 0.996100383889179
	}
}

over &amp;#34;sphere_7&amp;#34; (
	prepend references = @./sphere_base.usd@
)
{
	double3 xformOp:translate = (0.6139729851730387, -2.1636073894804015, -1.2448903303953696)
	uniform token[] xformOpOrder = [&amp;#34;xformOp:translate&amp;#34;]
	over &amp;#34;sphere&amp;#34;
	{
		color3f[] primvars:displayColor = [(0.7496581061490399, 0.6634379091934232, 0.5005325739057677)]
		double radius = 1.019717277295782
	}
}

over &amp;#34;sphere_8&amp;#34; (
	prepend references = @./sphere_base.usd@
)
{
	double3 xformOp:translate = (1.8976158439642976, 2.6610769940080488, -2.983000650753242)
	uniform token[] xformOpOrder = [&amp;#34;xformOp:translate&amp;#34;]
	over &amp;#34;sphere&amp;#34;
	{
		color3f[] primvars:displayColor = [(0.40540766717836174, 0.3829469193133114, 0.8038967224000645)]
		double radius = 1.0486640607196256
	}
}

over &amp;#34;sphere_9&amp;#34; (
	prepend references = @./sphere_base.usd@
)
{
	double3 xformOp:translate = (1.7544553609781461, 3.6112312528391275, -1.0795222118663084)
	uniform token[] xformOpOrder = [&amp;#34;xformOp:translate&amp;#34;]
	over &amp;#34;sphere&amp;#34;
	{
		color3f[] primvars:displayColor = [(0.36375574825435375, 0.4873766098052579, 0.2602608790257742)]
		double radius = 0.8077356270763054
	}
}

over &amp;#34;sphere_10&amp;#34; (
	prepend references = @./sphere_base.usd@
)
{
	double3 xformOp:translate = (-3.1792781878340888, 0.6093081424155065, 2.663220325702283)
	uniform token[] xformOpOrder = [&amp;#34;xformOp:translate&amp;#34;]
	over &amp;#34;sphere&amp;#34;
	{
		color3f[] primvars:displayColor = [(0.8799012009411763, 0.7636616404114634, 0.661145399339866)]
		double radius = 1.2028816672373872
	}
}

over &amp;#34;sphere_11&amp;#34; (
	prepend references = @./sphere_base.usd@
)
{
	double3 xformOp:translate = (-2.1455875292572246, -3.464486780123318, 3.4854264040544267)
	uniform token[] xformOpOrder = [&amp;#34;xformOp:translate&amp;#34;]
	over &amp;#34;sphere&amp;#34;
	{
		color3f[] primvars:displayColor = [(0.5864557819094003, 0.5480884060810113, 0.608442805757727)]
		double radius = 1.5136281018955642
	}
}

over &amp;#34;sphere_12&amp;#34; (
	prepend references = @./sphere_base.usd@
)
{
	double3 xformOp:translate = (-2.720272864042377, 1.1241795502758443, 3.0341149159083036)
	uniform token[] xformOpOrder = [&amp;#34;xformOp:translate&amp;#34;]
	over &amp;#34;sphere&amp;#34;
	{
		color3f[] primvars:displayColor = [(0.9908854203828784, 0.833821856282827, 0.5439826142768127)]
		double radius = 0.9554204991635202
	}
}
&lt;/code&gt;&lt;/pre&gt;</description>
    </item>
    
    
    
    <item>
      <title>Hello USD - Part 5: Python setup pt 2, what really works</title>
      <link>https://whynotestflight.com/excuses/hello-usd-part-5-python-setup-pt-2-what-really-works/</link>
      <pubDate>Sun, 02 Jul 2023 00:00:00 +0000</pubDate>
      
      <guid>https://whynotestflight.com/excuses/hello-usd-part-5-python-setup-pt-2-what-really-works/</guid>
      <description>&lt;p&gt;The post assumes some familiarity with &lt;a href=&#34;https://whynotestflight.com/excuses/hello-usd-part-4-python-setup/&#34;&gt;yesterdays post&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;To skip to the write up of what works go to: &lt;a href=&#34;https://github.com/carlynorama/USDHelloWorld/blob/main/SETUP.md&#34;&gt;https://github.com/carlynorama/USDHelloWorld/blob/main/SETUP.md&lt;/a&gt;&lt;/p&gt;
&lt;h1 id=&#34;the-last-hold-out&#34;&gt;The last hold out&lt;/h1&gt;
&lt;p&gt;Pixar includes a viewer utility in with their USD python tools. It&amp;rsquo;s why to include PyOPenGL and PySide6 (Qt, cross platform UI tool).&lt;/p&gt;
&lt;p&gt;&lt;code&gt;usdview&lt;/code&gt; takes one parameter, the name of a file like below.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-zsh&#34; data-lang=&#34;zsh&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;usdview HelloWorld.usda 
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;I didn&amp;rsquo;t have a single build that could run it without errors or crashing. The first time I ran that command using my &lt;code&gt;pyenv&lt;/code&gt; 3.7.9 build I got the following error message&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;State file not found, a new one will be created.
Traceback (most recent call last):
  File &amp;#34;/Users/$USER/opb/USDefault379/bin/usdview&amp;#34;, line 35, in &amp;lt;module&amp;gt;
    Usdviewq.Launcher().Run()
  File &amp;#34;/Users/$USER/opb/USDefault379/lib/python/pxr/Usdviewq/__init__.py&amp;#34;, line 86, in Run
    self.__LaunchProcess(arg_parse_result)
  File &amp;#34;/Users/$USER/opb/USDefault379/lib/python/pxr/Usdviewq/__init__.py&amp;#34;, line 396, in __LaunchProcess
    (app, appController) = self.LaunchPreamble(arg_parse_result)
  File &amp;#34;/Users/$USER/opb/USDefault379/lib/python/pxr/Usdviewq/__init__.py&amp;#34;, line 386, in LaunchPreamble
    appController = AppController(arg_parse_result, contextCreator)
  File &amp;#34;/Users/$USER/opb/USDefault379/lib/python/pxr/Usdviewq/appController.py&amp;#34;, line 410, in __init__
    self._dataModel = UsdviewDataModel(self._makeTimer, self._configManager.settings)
  File &amp;#34;/Users/$USER/opb/USDefault379/lib/python/pxr/Usdviewq/appController.py&amp;#34;, line 128, in __init__
    self._viewSettingsDataModel = ViewSettingsDataModel(self, settings)
  File &amp;#34;/Users/$USER/opb/USDefault379/lib/python/pxr/Usdviewq/viewSettingsDataModel.py&amp;#34;, line 136, in __init__
    QtCore.QObject.__init__(self)
TypeError: __init__() missing 2 required positional arguments: &amp;#39;parent&amp;#39; and &amp;#39;name&amp;#39;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;At this point I&amp;rsquo;d been having enough trouble that I was probably missing obvious things and should go get help: &lt;a href=&#34;https://github.com/PixarAnimationStudios/OpenUSD/issues/2520&#34;&gt;https://github.com/PixarAnimationStudios/OpenUSD/issues/2520&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;I learned that &lt;code&gt;pip3 install PySide6==6.4.3&lt;/code&gt; would have been a better choice for my set up.&lt;/p&gt;
&lt;p&gt;Honestly if I&amp;rsquo;d had actually &lt;em&gt;scrolled down&lt;/em&gt; the &lt;a href=&#34;https://github.com/PixarAnimationStudios/OpenUSD/blob/release/VERSIONS.md&#34;&gt;install versions page&lt;/a&gt; and used those recommended versions, that would have been smart!&lt;/p&gt;
&lt;p&gt;Reinstalling PySide and recompiling got &lt;code&gt;usdview&lt;/code&gt; to open!!! YAY!! but only briefly before it crashed, unable to find OpenGL.&lt;/p&gt;
&lt;p&gt;I did try a trick mentioned on a different &lt;a href=&#34;https://github.com/PixarAnimationStudios/OpenUSD/issues/1372#issuecomment-823226088&#34;&gt;GitHub issue&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;pip3 install PyOpenGL PyOpenGL_accelerate&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Which strangely got my &lt;code&gt;pyenv&lt;/code&gt; 3.7.9 build &lt;code&gt;usdview&lt;/code&gt; to behave the same as my system install of 3.7.9&amp;rsquo;s &lt;code&gt;usdview&lt;/code&gt;- Where it opens and DOESN&amp;rsquo;T crash, but also doesn&amp;rsquo;t render, and still complains it can&amp;rsquo;t find OpenGL, printing out an error message .&lt;/p&gt;
&lt;h2 id=&#34;mystery-solved&#34;&gt;Mystery Solved&lt;/h2&gt;
&lt;p&gt;The folks part of Academy Software Foundation USD working group slack rock.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://wiki.aswf.io/display/WGUSD/USD+Working+Group&#34;&gt;https://wiki.aswf.io/display/WGUSD/USD+Working+Group&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://wiki.aswf.io/display/WGUSD/USD+Resources&#34;&gt;https://wiki.aswf.io/display/WGUSD/USD+Resources&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/AcademySoftwareFoundation/wg-usd&#34;&gt;https://github.com/AcademySoftwareFoundation/wg-usd&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://www.aswf.io/get-involved/&#34;&gt;https://www.aswf.io/get-involved/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;From them I learned Apple changed how frameworks were stored between macOS 10 and macOS 11. Python 3.9 has the patch. If I really really read the version page, they do in fact indicate they were using MacOS 10.&lt;/p&gt;
&lt;p&gt;Switching my pyenv to 3.9 made everything work perfectly as far as I can tell.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;workingUSDView.png&#34; alt=&#34;Screenshot of the USDView interface displaying the hello world sphere. It also displaces the usd tree and other information about the stage such as the World Bounding Box, and materials that the USD is using. In this case none. There is a search box for a property name as well.&#34;&gt;&lt;/p&gt;
&lt;p&gt;SUCCESS.&lt;/p&gt;
&lt;h2 id=&#34;trouble-shooting-dynamic-library-paths&#34;&gt;Trouble shooting Dynamic Library Paths&lt;/h2&gt;
&lt;p&gt;To be honest, when I first looked at the output of the OpenGL error I assumed it was just assuring me it was traversing my $PATH. As list of places to look for binaries, I admit I thought was a weird for that to be used to go looking for OpenGL, a system Framework. But once the Framework handling change was mentioned, I realized that of course it wasn&amp;rsquo;t my PATH, it was the LD_LIBRARY_PATH, which is the essentially the $PATH but for the system to find the shared libraries that compiled binaries depend on. In the future, a reminder that it is always helpful to run the below when working with unfamiliar projects.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-sh&#34; data-lang=&#34;sh&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# when you know the full path example&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;otool -L &lt;span style=&#34;color:#f4dbd6&#34;&gt;$BUILD_FOLDER&lt;/span&gt;/bin/usdcat
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# for pulling out the path of a binary in the $PATH example&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;otool -L &lt;span style=&#34;color:#a6da95&#34;&gt;`&lt;/span&gt;which python3&lt;span style=&#34;color:#a6da95&#34;&gt;`&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;From &lt;code&gt;man otool&lt;/code&gt; about the option &lt;code&gt;-L&lt;/code&gt;: &amp;ldquo;Display the names and version numbers of the shared libraries that the object file uses, as well as the shared library ID if the file is a shared library.&amp;rdquo; On Apple platforms these can also be called &amp;ldquo;dynamic libraries&amp;rdquo;.&lt;/p&gt;
&lt;p&gt;What displays at the beginning of each list entry is the path the system looks for the library in. If it doesn&amp;rsquo;t have an &lt;code&gt;@&lt;/code&gt; at the beginning of that path it&amp;rsquo;s hard coded, and if your system doesn&amp;rsquo;t have it you&amp;rsquo;re almost out of luck. Don&amp;rsquo;t panic if they aren&amp;rsquo;t all &lt;code&gt;@&lt;/code&gt;, &lt;code&gt;/System/Library&lt;/code&gt; links and &lt;code&gt;/usr/lib&lt;/code&gt; links frequently work out if you are targeting machines running the same OS as the one you build on. But that doesn&amp;rsquo;t always stay true over time, e.g. the need to do a system install of Python 3.7.9 for USDZ Tools.&lt;/p&gt;
&lt;p&gt;To dig further in to the &lt;code&gt;@&lt;/code&gt;&amp;rsquo;s, i.e. the dynamic libraries, use &lt;code&gt;-l&lt;/code&gt; (&amp;ldquo;Display the load commands.&amp;rdquo;) which includes further descriptions.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-sh&#34; data-lang=&#34;sh&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## when you know the full path example&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;otool -l &lt;span style=&#34;color:#f4dbd6&#34;&gt;$BUILD_FOLDER&lt;/span&gt;/bin/usdcat
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## for pulling out the path of a binary in the $PATH example&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;otool -l &lt;span style=&#34;color:#a6da95&#34;&gt;`&lt;/span&gt;which python3&lt;span style=&#34;color:#a6da95&#34;&gt;`&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## Limit the search&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;otool -l &lt;span style=&#34;color:#f4dbd6&#34;&gt;$BUILD_FOLDER&lt;/span&gt;/bin/usdcat | grep RPATH -A2
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## if usdcat is in path already&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;otool -l &lt;span style=&#34;color:#a6da95&#34;&gt;`&lt;/span&gt;which usdcat&lt;span style=&#34;color:#a6da95&#34;&gt;`&lt;/span&gt; | grep RPATH -A2
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;In the results will be the tree of places the linker will look. For &lt;code&gt;usdcat&lt;/code&gt;, where the results say &lt;code&gt;@loader_path&lt;/code&gt;, it would be the equivalent of &lt;code&gt;$BUILD_FOLDER/bin/&lt;/code&gt;, i.e. the place where the binary being inspected lives.&lt;/p&gt;
&lt;p&gt;But what if binaries throw an error related to one of these paths?&lt;/p&gt;
&lt;p&gt;Run &lt;code&gt;man dyld&lt;/code&gt;, the list at the top are all the variables one can theoretically change about where a the computer will look for a dynamic library. Unless very very very sure, don&amp;rsquo;t mess with this. In fact, &lt;a href=&#34;https://support.apple.com/en-us/HT204899&#34;&gt;&lt;code&gt;System Integrity Protection&lt;/code&gt;&lt;/a&gt; will stop/ignore changes. It&amp;rsquo;s that bad. With SIP &lt;a href=&#34;https://developer.apple.com/documentation/security/disabling_and_enabling_system_integrity_protection&#34;&gt;disabled&lt;/a&gt;, one CAN update these paths like $PATH, but wow, that&amp;rsquo;s a commitment, and a sign to look for another way. I&amp;rsquo;m not even going to show how, because it&amp;rsquo;s that bad of an idea unless it&amp;rsquo;s like a single board computer dedicated to a single cause and there is no other way because the clock is ticking and you&amp;rsquo;re in the field&amp;hellip; anyway you get the drill.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;m glad there was another way.&lt;/p&gt;
&lt;h2 id=&#34;apples-usdz-tools&#34;&gt;Apple&amp;rsquo;s USDZ Tools&lt;/h2&gt;
&lt;p&gt;The framework change issue made me question if the Apple compiled USDZ Tools that REQUIRE 3.7.9 are really working on my setup as well as I thought they were. All in all, not perfect but a lot does work. This is on my macOS 11 box, so it&amp;rsquo;s possible results would be different on one running macOS 13.4.&lt;/p&gt;
&lt;p&gt;Test results:&lt;/p&gt;
&lt;h3 id=&#34;usd-folder&#34;&gt;USD folder&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Can run with -h or sample file: usdchecker, usdcat, uddiff, usddumpcrate, usdedit, usdresolve, usdtree, usdzip&lt;/li&gt;
&lt;li&gt;usdzcreate: fails, links to Python v2.7&lt;/li&gt;
&lt;li&gt;items in lib not tested&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;samples&#34;&gt;samples&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;working: 101, 102, 107, 108, 201&lt;/li&gt;
&lt;li&gt;failing: 103, 104, 105, 106, 202  (Boost.Python.ArgumentError: Python argument types in Output.ConnectToSource(Output, Shader, str) did not match C++ signature)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Boost errors never come as a true surprise because it&amp;rsquo;s everywhere. &lt;a href=&#34;https://www.boost.org/doc/libs/&#34;&gt;Boost&lt;/a&gt; is like a crazy Standard Library for C++, which I think you&amp;rsquo;ll find not so &amp;ldquo;Standard&amp;rdquo; anymore. (Insert Prince Humperdinck meme)&lt;/p&gt;
&lt;h3 id=&#34;usdzconvert&#34;&gt;usdzconvert&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Can run with -h or sample file: usdzaudioimport, usdzconvert, usdzcreateassetlib&lt;/li&gt;
&lt;li&gt;usdARKitChecker: fails, links to Python v2.7&lt;/li&gt;
&lt;li&gt;fixOpacity: fails, No module named PIL&lt;/li&gt;
&lt;li&gt;python scripts not tested directly since they don&amp;rsquo;t have mains mostly&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Feedback No: FB12499226&lt;/p&gt;
&lt;p&gt;All in all I feel in good shape to enjoy the holiday without dangling threads in regards to OpenUSD builds.&lt;/p&gt;
&lt;p&gt;Back in a few.&lt;/p&gt;
</description>
    </item>
    
    
    
    <item>
      <title>Hello USD - Part 4: Python setup</title>
      <link>https://whynotestflight.com/excuses/hello-usd-part-4-python-setup/</link>
      <pubDate>Sat, 01 Jul 2023 00:00:00 +0000</pubDate>
      
      <guid>https://whynotestflight.com/excuses/hello-usd-part-4-python-setup/</guid>
      <description>&lt;p&gt;UPDATE - Most of what&amp;rsquo;s in this post ended up being educational, but a bad path. Actually working instructions instead of the travelogue: &lt;a href=&#34;https://github.com/carlynorama/USDHelloWorld/blob/main/SETUP.md&#34;&gt;https://github.com/carlynorama/USDHelloWorld/blob/main/SETUP.md&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;A post in 5 Acts.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Act 1: Naively trying to use current version of Python&lt;/li&gt;
&lt;li&gt;Act 2: Getting the Apple Provided USDZ Tools working using a system package install of python 3.7.9&lt;/li&gt;
&lt;li&gt;Act 3: Getting the Pixar python libraries working with the same set up&lt;/li&gt;
&lt;li&gt;Act 4: Getting the Pixar python libraries working using a &lt;a href=&#34;https://github.com/pyenv/pyenv&#34;&gt;&lt;code&gt;pyenv&lt;/code&gt;&lt;/a&gt; install of 3.7.9&lt;/li&gt;
&lt;li&gt;Act 5: It DOES sort of work with 3.11???&lt;/li&gt;
&lt;li&gt;Post Credits Scene: &lt;code&gt;usdview&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;knowledge-prereq&#34;&gt;Knowledge Prereq&lt;/h3&gt;
&lt;p&gt;This post assumes significant understanding about the command line, PATH, PYTHONPATH, editing shell profiles and the vagaries of managing python environments.&lt;/p&gt;
&lt;p&gt;Echoing yesterday all my USD builds live in a local user folder together with the pattern &lt;code&gt;~/opb/$SOME_BUILD_NAME&lt;/code&gt; none are currently added to the global path as this post will explore. &lt;code&gt;opb&lt;/code&gt; stands for &amp;ldquo;off path bin&amp;rdquo; and it&amp;rsquo;s personal style, not anything official.&lt;/p&gt;
&lt;h3 id=&#34;software--hardware&#34;&gt;Software &amp;amp; Hardware&lt;/h3&gt;
&lt;p&gt;Act 1: Same set up as yesterday.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Intel chip&lt;/li&gt;
&lt;li&gt;MacOS 13.4&lt;/li&gt;
&lt;li&gt;Xcode 14.3.1 &amp;amp; the command line tools&lt;/li&gt;
&lt;li&gt;Homebrew 4.0.26 with brew upgrade run 2023-06-30&lt;/li&gt;
&lt;li&gt;optional: VSCode, plugins for C++, CMake and Python from Microsoft and USD plugin from Animal Logic for inspection.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Acts 2 &amp;amp; 3 successfully executed on:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Intel Chip&lt;/li&gt;
&lt;li&gt;MacOS 11.7.2&lt;/li&gt;
&lt;li&gt;Xcode 13.1 13A1030d &amp;amp; 13.2.0.0.1.163848880 for CLI  (&lt;code&gt;xcodebuild -version&lt;/code&gt; vs &lt;code&gt;pkgutil --pkg-info=com.apple.pkg.DeveloperToolsCLI&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Homebrew 4.0.26 with brew upgrade run 2023-06-30&lt;/li&gt;
&lt;li&gt;optional: VSCode, plugins for C++, CMake and Python from Microsoft and USD plugin from Animal Logic for inspection.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Act 4&amp;amp;5:&lt;/p&gt;
&lt;p&gt;Same as Act 1, Act 5 is essentially Act 1 run on a similarly configured M1&lt;/p&gt;
&lt;h2 id=&#34;act-1-doh-well-that-didnt-work&#34;&gt;Act 1: Doh&amp;hellip; Well that didn&amp;rsquo;t work.&lt;/h2&gt;
&lt;p&gt;What happens if you try to do one of the Pixar python based tutorials after running the default build script from the Pixar repo on a system using Python 3.11?&lt;/p&gt;
&lt;p&gt;Doing the default build is similar to yesterday&amp;rsquo;s install of just the C++ but there are some prerequisites. &lt;code&gt;usdview&lt;/code&gt; requires PyOpenGL and PySide6. If you don&amp;rsquo;t want &lt;code&gt;usdview&lt;/code&gt;, leave out installing them and add the &lt;code&gt;--no-usdview&lt;/code&gt; to the build (shown in Act 3)&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-zsh&#34; data-lang=&#34;zsh&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# if you care about isolating your system python and your playtime python and haven&amp;#39;t already&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# brew install python3 &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# rehash&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# which pip3 #to confirm using desired versions&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;pip3 install PyOpenGL
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# pip3 install PySide6 # &amp;lt;- Bug in USD 23.05 PySide6 &amp;gt;= 6.5.0 &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;pip3 install &lt;span style=&#34;color:#f4dbd6&#34;&gt;PySide6&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;==&lt;/span&gt;6.4.3 &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# &amp;lt;- UPDATED see epilogue&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#91d7e3&#34;&gt;cd&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;$DIRECTORY_WITH_CLONED_REPO&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;python3 USD/build_scripts/build_usd.py ~/opb/USDefault
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;After the build completes:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;cd $DIRECTORY_WITH_FILES_TO_CONVERT #See yesterday&amp;#39;s post
~/opb/USDefault/bin/usdcat -o threeBodyExample_fromArchive.usda ThreeBodyUSDZ.usdz
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;All works just fine.&lt;/p&gt;
&lt;p&gt;Moving on to trying to try Hello World again&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-sh&#34; data-lang=&#34;sh&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#91d7e3&#34;&gt;export&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;PATH&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;$PATH&lt;/span&gt;:&lt;span style=&#34;color:#f4dbd6&#34;&gt;$HOME&lt;/span&gt;/opb/USDefault/bin;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#91d7e3&#34;&gt;export&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;PYTHONPATH&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;$PYTHONPATH&lt;/span&gt;:&lt;span style=&#34;color:#f4dbd6&#34;&gt;$HOME&lt;/span&gt;/opb/USDefault/lib/python
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;python3
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;In REPL:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8bd5ca&#34;&gt;from&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;pxr&lt;/span&gt; &lt;span style=&#34;color:#8bd5ca&#34;&gt;import&lt;/span&gt; Usd, UsdGeom
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;produces the following error&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;Traceback (most recent call last):
  File &amp;#34;&amp;lt;stdin&amp;gt;&amp;#34;, line 1, in &amp;lt;module&amp;gt;
  File &amp;#34;/Users/$USER/opb/USDefault/lib/python/pxr/Usd/__init__.py&amp;#34;, line 25, in &amp;lt;module&amp;gt;
    Tf.PreparePythonModule()
  File &amp;#34;/Users/$USER/opb/USDefault/lib/python/pxr/Tf/__init__.py&amp;#34;, line 88, in PreparePythonModule
    module = importlib.import_module(
             ^^^^^^^^^^^^^^^^^^^^^^^^
  File &amp;#34;/usr/local/Cellar/python@3.11/3.11.4_1/Frameworks/Python.framework/Versions/3.11/lib/python3.11/importlib/__init__.py&amp;#34;, line 126, in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
SystemError: type Boost.Python.enum has the Py_TPFLAGS_HAVE_GC flag but has no traverse function
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;At this point I walked away because I didn&amp;rsquo;t have the expectation that the Python scripts would with work this version of Python anyway. 3.11 is way different than the 3.7.7 Pixar mention on their &lt;a href=&#34;https://github.com/PixarAnimationStudios/OpenUSD/blob/release/VERSIONS.md&#34;&gt;build machine description page&lt;/a&gt;.  Perusing the &lt;a href=&#34;https://docs.python.org/3.11/reference/import.html&#34;&gt;Python 3.11 docs on importing&lt;/a&gt; alone shows a myriad of changes in 3.10.&lt;/p&gt;
&lt;p&gt;UPDATE: See Act 5&lt;/p&gt;
&lt;h2 id=&#34;act-2-usdz-tools-hello-world&#34;&gt;Act 2: USDZ Tools Hello World&lt;/h2&gt;
&lt;p&gt;UPDATE: The USDZ scrips work better when run using a fresh build of the Pixar tools in the path instead and then running the script with the preferred python explicitly: e.g. &lt;code&gt;python3 /Applications/usdpython/usdzconvert/usdARKitChecker -v three_d_thing.usda&lt;/code&gt;&lt;/p&gt;
&lt;h3 id=&#34;step-1-go-get-python-37-the-hard-way&#34;&gt;Step 1: Go Get Python 3.7 the hard way&lt;/h3&gt;
&lt;p&gt;The &lt;a href=&#34;https://developer.apple.com/augmented-reality/tools/&#34;&gt;Apple USDZ Tools&lt;/a&gt; are comprised of the USD libraries (version 22.03), plus some other helper scripts pre-compiled using Python 3.7.9&lt;/p&gt;
&lt;p&gt;So 3.7.9 it is.&lt;/p&gt;
&lt;p&gt;Needing to manage multiple python environments happens all the time&amp;hellip; HOWEVER&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;3.7 is no longer available as a cask on homebrew at any version&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/pyenv/pyenv&#34;&gt;&lt;code&gt;pyenv&lt;/code&gt;&lt;/a&gt; DOES maintain a copy of 3.7.9, but unfortunately won&amp;rsquo;t work with the pre compiled libraries without some crazy symlinking, and then that&amp;rsquo;s a maybe, so I moved on.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Why doesn&amp;rsquo;t &lt;code&gt;pyenv&lt;/code&gt; work with the USDZ Tools? Since the Apple tools are pre-compiled, the environment needs to perfectly match the one it was built for and the build appears to have a dependency directly to &lt;code&gt;/Library/Frameworks/Python.framework/Versions/3.7/Python&lt;/code&gt;, (thanks &lt;a href=&#34;https://www.unix.com/man-page/osx/1/otool/&#34;&gt;&lt;code&gt;otool -L /Applications/usdpython/USD/lib/python/pxr/Tf/_tf.so&lt;/code&gt;&lt;/a&gt; for helping make sense of the error message)&lt;/p&gt;
&lt;p&gt;So python.org download we go. &lt;a href=&#34;https://www.python.org/downloads/release/python-379/&#34;&gt;https://www.python.org/downloads/release/python-379/&lt;/a&gt; Python.org does not recommend or support 3.7 anymore, but there remains an installer on the page (20230629).&lt;/p&gt;
&lt;p&gt;After running the installer, find the &lt;code&gt;Python 3.7&lt;/code&gt; folder in &lt;code&gt;/Applications&lt;/code&gt; and run the &lt;code&gt;Install Certificates.command&lt;/code&gt; file.&lt;/p&gt;
&lt;p&gt;The installer seems to also update &lt;code&gt;.zprofile&lt;/code&gt; (or respective shell profile) to contain the below lines. If it doesn&amp;rsquo;t, run the &lt;code&gt;Update Shell Profile.command&lt;/code&gt; to do so. WARNING: This will now set python 3.7.9 as the default for EVERY shell window because it puts 3.7 at the front of the line.  Fixed in step 4, but at this point I went with it.&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;PATH=&amp;#34;/Library/Frameworks/Python.framework/Versions/3.7/bin:${PATH}&amp;#34;
export PATH
&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=&#34;step-2-go-get-the-precompiled-files-from-apple&#34;&gt;Step 2: Go get the precompiled files from Apple&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://developer.apple.com/augmented-reality/tools/&#34;&gt;USDZ Tools bundle&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;For reference if removed from page: &lt;a href=&#34;https://developer.apple.com/augmented-reality/tools/files/USDPython-pkg.zip&#34;&gt;https://developer.apple.com/augmented-reality/tools/files/USDPython-pkg.zip&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;As it turns out USDZ Tools provides a handy installer (20230629 - version 0.66, from 2019, Compiled for python 3.7.9, using USD version 22.03)&lt;/p&gt;
&lt;h3 id=&#34;step-3-run-them-using-their-shell-launcher&#34;&gt;Step 3: Run them using their shell launcher&lt;/h3&gt;
&lt;p&gt;After the install, as recommended in the installer docs (DO NOT SKIP READING THEM), I double clicked on the &lt;code&gt;USD.command&lt;/code&gt; file in &lt;code&gt;/Applications/usdpython&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;At this point &lt;code&gt;python3 --version&lt;/code&gt; did show 3.7.9 and &lt;code&gt;echo $PYTHONPATH&lt;/code&gt; did include &lt;code&gt;/Applications/usdpython/USD/lib/python&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;python3 /Applications/usdpython/samples/101_scenegraph.py&lt;/code&gt; produced&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-usd&#34; data-lang=&#34;usd&#34;&gt;#usda 1.0
(
    defaultPrim = &amp;#34;scenegraph&amp;#34;
    upAxis = &amp;#34;Y&amp;#34;
)

def Xform &amp;#34;scenegraph&amp;#34; (
    assetInfo = {
        asset identifier = @scenegraph.usd@
        string name = &amp;#34;scenegraph&amp;#34;
    }
    kind = &amp;#34;component&amp;#34;
)
{
    def Scope &amp;#34;Geom&amp;#34;
    {
        def Cube &amp;#34;cube&amp;#34;
        {
        }

        def Sphere &amp;#34;sphere&amp;#34;
        {
            double3 xformOp:translate = (4, 0, 0)
            uniform token[] xformOpOrder = [&amp;#34;xformOp:translate&amp;#34;]
        }
    }
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;I had a little dance party in my soul after seeing this. It had been multiple hours over multiple days to get to this point.  I&amp;rsquo;ve glossed over a number of failed builds. On the other hand I was also pretty annoyed being stuck having 3.7.9 as my main version of Python on the machine I wanted to do any USD python work on.&lt;/p&gt;
&lt;h3 id=&#34;step-4-corral-379-into-just-the-shell-its-wanted-for&#34;&gt;Step 4: Corral 3.7.9 into just the shell it&amp;rsquo;s wanted for&lt;/h3&gt;
&lt;p&gt;I brute forced returning to python 3.11 (&lt;code&gt;brew install python&lt;/code&gt;, &lt;code&gt;brew reinstall python@3.11&lt;/code&gt;, &lt;code&gt;brew link --overwrite python@3.11&lt;/code&gt;). I was tired. It was late. That may not have been necessary. I also removed&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-sh&#34; data-lang=&#34;sh&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;PATH&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;/Library/Frameworks/Python.framework/Versions/3.7/bin:&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;${&lt;/span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;PATH&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;}&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#91d7e3&#34;&gt;export&lt;/span&gt; PATH
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;from &lt;code&gt;.zprofile&lt;/code&gt; and added it to the top of &lt;code&gt;/Applications/usdpython/USD.command&lt;/code&gt; (&lt;code&gt;sudo nano /Applications/usdpython/USD.command&lt;/code&gt; because we aren&amp;rsquo;t in a user editable folder) and launched it again.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;USD.command&lt;/code&gt; now looked like:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-sh&#34; data-lang=&#34;sh&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#!/bin/sh
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# ADDED uncomment below for error checking&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# env &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;##### ADDED TO WORK WITH PYTHON 3.7&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;PATH&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;/Library/Frameworks/Python.framework/Versions/3.7/bin:&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;${&lt;/span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;PATH&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;}&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#91d7e3&#34;&gt;export&lt;/span&gt; PATH
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;##################################&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;BASEPATH&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;$(&lt;/span&gt;dirname &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;$0&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#Note: The double path is in provided USD.command file, I left it alone. &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#91d7e3&#34;&gt;export&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;PATH&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;$PATH&lt;/span&gt;:&lt;span style=&#34;color:#f4dbd6&#34;&gt;$BASEPATH&lt;/span&gt;/USD:&lt;span style=&#34;color:#f4dbd6&#34;&gt;$PATH&lt;/span&gt;:&lt;span style=&#34;color:#f4dbd6&#34;&gt;$BASEPATH&lt;/span&gt;/usdzconvert;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#91d7e3&#34;&gt;export&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;PYTHONPATH&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;$PYTHONPATH&lt;/span&gt;:&lt;span style=&#34;color:#f4dbd6&#34;&gt;$BASEPATH&lt;/span&gt;/USD/lib/python
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# uncomment to set the PYTHONPATH to FBX Bindings here:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# export PYTHONPATH=$PYTHONPATH:&amp;#34;/Applications/Autodesk/FBX Python SDK/2020.2.1/lib/Python37_x64&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;[[&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;$PYTHONPATH&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;==&lt;/span&gt; *&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;FBX&amp;#34;&lt;/span&gt;* &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;]]&lt;/span&gt;; &lt;span style=&#34;color:#c6a0f6&#34;&gt;then&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    :
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;else&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#91d7e3&#34;&gt;echo&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;For FBX support, edit PYTHONPATH in this file (USD.command) or your shell configuration file&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;fi&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;$SHELL&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;python3 /Applications/usdpython/samples/101_scenegraph.py&lt;/code&gt; worked again! And I can still use Python 3.11 as my default install in other shells. Dance party for real.&lt;/p&gt;
&lt;h2 id=&#34;act-3-going-back-to-the-pure-pixar-library&#34;&gt;ACT 3: Going back to the Pure Pixar Library&lt;/h2&gt;
&lt;p&gt;Launching a terminal using the USD.command file to take advantage of the quick load of python 3.7.9, I ran:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-sh&#34; data-lang=&#34;sh&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#91d7e3&#34;&gt;cd&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;$DIR_WITH_CLONED_REPO&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;python3 USD/build_scripts/build_usd.py --no-usdview ~/opb/USD379NoView
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Note: This version of the install requires no extra python dependencies, because it DOES NOT include &lt;code&gt;usdview&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;I had gotten to something like this point before, but now I:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;made a copy of USD.command called &lt;code&gt;USD_pixar_noview.command&lt;/code&gt; in &lt;code&gt;~/opb/&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;edited the location information&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chmod 755 usd_pixar_noview.command&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The updated &lt;code&gt;USD_pixar_noview.command&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-sh&#34; data-lang=&#34;sh&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#!/bin/sh
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# ADDED uncomment below for error checking&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# env &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;##### ADDED TO WORK WITH PYTHON 3.7&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;PATH&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;/Library/Frameworks/Python.framework/Versions/3.7/bin:&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;${&lt;/span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;PATH&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;}&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#91d7e3&#34;&gt;export&lt;/span&gt; PATH
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;##################################&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;BASEPATH&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;$(&lt;/span&gt;dirname &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;$0&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# Removed duplication &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#91d7e3&#34;&gt;export&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;PATH&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;$PATH&lt;/span&gt;:&lt;span style=&#34;color:#f4dbd6&#34;&gt;$BASEPATH&lt;/span&gt;/USD379NoView/bin;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#91d7e3&#34;&gt;export&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;PYTHONPATH&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;$PYTHONPATH&lt;/span&gt;:&lt;span style=&#34;color:#f4dbd6&#34;&gt;$BASEPATH&lt;/span&gt;/USD379NoView/lib/python
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# uncomment to set the PYTHONPATH to FBX Bindings here:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# export PYTHONPATH=$PYTHONPATH:&amp;#34;/Applications/Autodesk/FBX Python SDK/2020.2.1/lib/Python37_x64&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;[[&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;$PYTHONPATH&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;==&lt;/span&gt; *&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;FBX&amp;#34;&lt;/span&gt;* &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;]]&lt;/span&gt;; &lt;span style=&#34;color:#c6a0f6&#34;&gt;then&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    :
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;else&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#91d7e3&#34;&gt;echo&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;For FBX support, edit PYTHONPATH in this file (USD_pixar_noview.command) or your shell configuration file&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;fi&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;$SHELL&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now to check:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-sh&#34; data-lang=&#34;sh&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#91d7e3&#34;&gt;echo&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;$PATH&lt;/span&gt; &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#looked good&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#91d7e3&#34;&gt;echo&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;$PYTHONPATH&lt;/span&gt; &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#looked good&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;python3 --version &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#looked good&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#91d7e3&#34;&gt;cd&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;$SOME_DIRECTORY_TO_WRITE_FILES_IN&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;python3 &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#open REPL&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;In the REPL, typed hello world example from &lt;a href=&#34;https://openusd.org/release/tut_helloworld.html&#34;&gt;https://openusd.org/release/tut_helloworld.html&lt;/a&gt;&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8bd5ca&#34;&gt;from&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;pxr&lt;/span&gt; &lt;span style=&#34;color:#8bd5ca&#34;&gt;import&lt;/span&gt; Usd, UsdGeom &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#This is the hard one... OMG IT WORKED!!!&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;stage &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; Usd&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;.&lt;/span&gt;Stage&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;.&lt;/span&gt;CreateNew(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#39;HelloWorld.usda&amp;#39;&lt;/span&gt;) &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# No error&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;xformPrim &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; UsdGeom&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;.&lt;/span&gt;Xform&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;.&lt;/span&gt;Define(stage, &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#39;/hello&amp;#39;&lt;/span&gt;) &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# No error again... could it be?&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;spherePrim &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; UsdGeom&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;.&lt;/span&gt;Sphere&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;.&lt;/span&gt;Define(stage, &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#39;/hello/world&amp;#39;&lt;/span&gt;) &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# getting close&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;stage&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;.&lt;/span&gt;GetRootLayer()&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;.&lt;/span&gt;Save() &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# Eyes closed.... AMAZING THE FILE APPEARS! &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# Cntrl-D to leave&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Every line worked and resulted in a &lt;code&gt;HelloWorld.usda&lt;/code&gt;!!!&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;#usda 1.0

def Xform &amp;#34;hello&amp;#34;
{
    def Sphere &amp;#34;world&amp;#34;
    {
    }
}
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&#34;act-4-trying-again-with-pyenv&#34;&gt;Act 4: Trying again with pyenv&lt;/h2&gt;
&lt;p&gt;Using &lt;code&gt;pyenv&lt;/code&gt; does not work for the precompiled USDZ Tools, but lets give it another chance with Pixar&amp;rsquo;s repo.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-zsh&#34; data-lang=&#34;zsh&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;brew install pyenv
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# brew install openssl readline sqlite3 xz zlib&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;pyenv install --list
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;pyenv install 3.7.9
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;pyenv init &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#to get instructions on how to configure your shell&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;For me &lt;code&gt;pyenv&lt;/code&gt; init said to:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-sh&#34; data-lang=&#34;sh&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# Load pyenv automatically by appending&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# the following to &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# ~/.zprofile (for login shells)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# and ~/.zshrc (for interactive shells) :&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#91d7e3&#34;&gt;export&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;PYENV_ROOT&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;$HOME&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;/.pyenv&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#91d7e3&#34;&gt;command&lt;/span&gt; -v pyenv &amp;gt;/dev/null &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;||&lt;/span&gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;export&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;PATH&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;$PYENV_ROOT&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;/bin:&lt;/span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;$PATH&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#91d7e3&#34;&gt;eval&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;$(&lt;/span&gt;pyenv init -&lt;span style=&#34;color:#c6a0f6&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# Restart your shell for the changes to take effect.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This means &lt;code&gt;pyenv&lt;/code&gt; will take over managing Python in every zsh shell (my default) and that&amp;rsquo;s what I want.&lt;/p&gt;
&lt;p&gt;Now to recompile with the new setup.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-zsh&#34; data-lang=&#34;zsh&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;pyenv shell 3.7.9
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;python3 --version &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# expected: 3.7.9&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;which pip3 &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#expected: /Users/$USER/.pyenv/shims/pip3&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;pip3 install PyOpenGL &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#if prompted to update pip, go ahead.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# pip3 install PySide6 &amp;lt;- Bug in USD 23.05 PySide6 &amp;gt;= 6.5.0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;pip3 install &lt;span style=&#34;color:#f4dbd6&#34;&gt;PySide6&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;==&lt;/span&gt;6.4.3 &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# &amp;lt;- UPDATE see epilogue&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#91d7e3&#34;&gt;cd&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;$DIRECTORY_WITH_CLONED_REPO&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;python3 USD/build_scripts/build_usd.py ~/opb/USDefault379
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now for yet another &lt;code&gt;.command&lt;/code&gt; file. This time to ask &lt;code&gt;pyenv&lt;/code&gt; to set it&amp;rsquo;s version to 3.7.9 and load the paths like before. I&amp;rsquo;ve written this one to live in the folder WITH the build. There are pros and cons to that. In this case the pro is that I should be able to use it without change in any new build folder. I&amp;rsquo;m calling it &lt;code&gt;USDBuildShellLauncher&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Don&amp;rsquo;t forget to chmod 755 &lt;code&gt;USDBuildShellLauncher.command&lt;/code&gt; once you set it up.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-zsh&#34; data-lang=&#34;zsh&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#!/bin/sh
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## uses pyenv to control version of python&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## after installing, run pyenv init in preferred&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;## shell for instructions to finish configuration.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#91d7e3&#34;&gt;export&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;PYENV_VERSION&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt;3.7.9
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;BASEPATH&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;$(&lt;/span&gt;dirname &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;$0&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#91d7e3&#34;&gt;export&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;PATH&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;$PATH&lt;/span&gt;:&lt;span style=&#34;color:#f4dbd6&#34;&gt;$BASEPATH&lt;/span&gt;/bin;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#91d7e3&#34;&gt;export&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;PYTHONPATH&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;$PYTHONPATH&lt;/span&gt;:&lt;span style=&#34;color:#f4dbd6&#34;&gt;$BASEPATH&lt;/span&gt;/lib/python
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;$SHELL&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Use &lt;code&gt;USDBuildShellLauncher.command&lt;/code&gt; to test it out&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-zsh&#34; data-lang=&#34;zsh&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#91d7e3&#34;&gt;cd&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;$DIRECTORY_WITH_FILES_TO_CONVERT&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# Note with the PATH being set we don&amp;#39;t need the full path in the command anymore&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;usdcat -o &lt;span style=&#34;color:#f4dbd6&#34;&gt;$OUTPUT&lt;/span&gt;.usda &lt;span style=&#34;color:#f4dbd6&#34;&gt;$INPUT&lt;/span&gt;.usdc
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#cd $SOME_DIRECTORY_TO_WRITE_FILES_IN #if necessary&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;python3 &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#open REPL&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;In the REPL, once again typing in the example from &lt;a href=&#34;https://openusd.org/release/tut_helloworld.html&#34;&gt;https://openusd.org/release/tut_helloworld.html&lt;/a&gt;&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8bd5ca&#34;&gt;from&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;pxr&lt;/span&gt; &lt;span style=&#34;color:#8bd5ca&#34;&gt;import&lt;/span&gt; Usd, UsdGeom &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#This is the hard one... OMG IT WORKED!!!&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;stage &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; Usd&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;.&lt;/span&gt;Stage&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;.&lt;/span&gt;CreateNew(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#39;HelloWorld.usda&amp;#39;&lt;/span&gt;) &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# No error&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;xformPrim &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; UsdGeom&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;.&lt;/span&gt;Xform&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;.&lt;/span&gt;Define(stage, &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#39;/hello&amp;#39;&lt;/span&gt;) &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# No error again... could it be?&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;spherePrim &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; UsdGeom&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;.&lt;/span&gt;Sphere&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;.&lt;/span&gt;Define(stage, &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#39;/hello/world&amp;#39;&lt;/span&gt;) &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# getting close&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;stage&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;.&lt;/span&gt;GetRootLayer()&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;.&lt;/span&gt;Save() &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# Eyes closed.... AMAZING THE FILE APPEARS! &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# Cntrl-D to leave&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Amazing!!!! It worked!!&lt;/p&gt;
&lt;h2 id=&#34;act-5&#34;&gt;Act 5&lt;/h2&gt;
&lt;p&gt;As it turns out&amp;hellip;&lt;/p&gt;
&lt;p&gt;If I hadn&amp;rsquo;t given up so easily, I might have gotten the USD python scrips kinda working in 3.11? I learned this by discussing the error I was getting with todbot. He&amp;rsquo;d duplicated my work on his machine and we were trying out multiple import statements to see if the errors changed.&lt;/p&gt;
&lt;p&gt;They did, and then they just stopped coming&amp;hellip;&lt;/p&gt;
&lt;p&gt;I went back to my machine and lo and behold, when opening a repl, running an import line and just an import line (e.g. &lt;code&gt;from pxr import Usd, UsdGeom&lt;/code&gt;) 3 times clears out the problems and then you can proceed. I haven&amp;rsquo;t run a script yet, but that&amp;rsquo;s interesting!&lt;/p&gt;
&lt;p&gt;ALSO - this is the ONLY build I&amp;rsquo;ve done (with corrected PySide6) that &lt;code&gt;usdview&lt;/code&gt; will work for me at all.&lt;/p&gt;
&lt;p&gt;I do think my 3.7.9 builds are certainly more stable than the 3.11 build, so they were worth the effort.&lt;/p&gt;
&lt;p&gt;But on that note, FIN.&lt;/p&gt;
&lt;h2 id=&#34;epilogue&#34;&gt;Epilogue&lt;/h2&gt;
&lt;p&gt;I have not really mentioned &lt;code&gt;usdview&lt;/code&gt; much even though some of the above builds have it. For one, I don&amp;rsquo;t really need it. &lt;code&gt;usdchecker&lt;/code&gt; provides more of what I want. But really I&amp;rsquo;ve been &lt;a href=&#34;https://github.com/PixarAnimationStudios/OpenUSD/issues/2520&#34;&gt;having some trouble with it&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Once I get some more success on that front I&amp;rsquo;ll make a post about it.&lt;/p&gt;
</description>
    </item>
    
    
    
    <item>
      <title>Hello USD - Part 3: Reality Composer is my USD WYSIWIG</title>
      <link>https://whynotestflight.com/excuses/hello-usd-part-3-reality-composer-is-my-usd-wysiwig/</link>
      <pubDate>Fri, 30 Jun 2023 00:00:00 +0000</pubDate>
      
      <guid>https://whynotestflight.com/excuses/hello-usd-part-3-reality-composer-is-my-usd-wysiwig/</guid>
      <description>&lt;p&gt;What I&amp;rsquo;ve written in this series so far has been aided by looking at USDZ files generated by Reality Composer and Blender. I&amp;rsquo;ve been using the &lt;code&gt;usdcat&lt;/code&gt; tool supplied in Pixar&amp;rsquo;s USD repo.&lt;/p&gt;
&lt;h3 id=&#34;knowledge-prereq&#34;&gt;Knowledge Prereq&lt;/h3&gt;
&lt;p&gt;This post assumes the reader is familiar with what CMake is and its role in building C++ projects. That said, Pixar has done all the hard work. The only thing to do is a copy paste of a couple of lines into a shell.&lt;/p&gt;
&lt;h3 id=&#34;software--hardware&#34;&gt;Software &amp;amp; Hardware:&lt;/h3&gt;
&lt;p&gt;Following along does not require any beta software.&lt;/p&gt;
&lt;p&gt;These steps have been tested on both Intel and Apple Silicon, no rosetta mode required.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;MacOS 13.4&lt;/li&gt;
&lt;li&gt;Xcode 14.3.1 &amp;amp; the command line tools&lt;/li&gt;
&lt;li&gt;Homebrew 4.0.26 with brew upgrade run 2023-06-30&lt;/li&gt;
&lt;li&gt;optional: VSCode, plugins for C++, CMake and Python from Microsoft and USD plugin from Animal Logic for inspection.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;step-1-get-a-usdc-file-from-a-reality-composer-project&#34;&gt;Step 1: Get a USDC file from a Reality Composer project&lt;/h2&gt;
&lt;p&gt;Most programs that create USD files compress them into &lt;a href=&#34;https://openusd.org/release/glossary.html#crate-file-format&#34;&gt;Crate files&lt;/a&gt; because the ASCII files get unwieldy. Thankfully, the folks at Pixar made a converter. Honestly this converter turns Reality Composer almost into a WYSIWIG. Super handy.&lt;/p&gt;
&lt;p&gt;Find Reality Composer via the &lt;code&gt;Xcode &amp;gt; Developer Tools &amp;gt; Reality Composer&lt;/code&gt; menu path in Xcode 14.&lt;/p&gt;
&lt;p&gt;I chose &lt;code&gt;New Document&lt;/code&gt; from the start up screen with a horizontal layout and threw some random objects into it. I did not turn on physics or accessibility at this time.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;realityComposerWindow.png&#34; alt=&#34;Screen shot of a Reality Composer window with 3 objects, a rock with an image texture, a purple cube and a blue capsule&#34;&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://developer.apple.com/documentation/realitykit/creating-3d-content-with-reality-composer&#34;&gt;https://developer.apple.com/documentation/realitykit/creating-3d-content-with-reality-composer&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Building AR Experiences with Reality Composer &lt;a href=&#34;https://developer.apple.com/videos/play/wwdc2019/609&#34;&gt;https://developer.apple.com/videos/play/wwdc2019/609&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;The artist’s AR toolkit &lt;a href=&#34;https://developer.apple.com/videos/play/wwdc2020/10601/&#34;&gt;https://developer.apple.com/videos/play/wwdc2020/10601/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;What was less clear than putting some objects on the stage, was needing to go into &lt;code&gt;Reality Composer &amp;gt; Settings&lt;/code&gt; to turn on the USDZ export.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;realityComposerSettings.png&#34; alt=&#34;Screenshot of a Reality Composer settings window. It is very small and only has about 5 things to edit, but the one that says Enable USDZ Export is checked.&#34;&gt;&lt;/p&gt;
&lt;p&gt;Once that box is ticked in the settings the File &amp;gt; Export menu will give the USDZ option. I chose &lt;code&gt;Current Scene&lt;/code&gt; rather than &lt;code&gt;Project&lt;/code&gt; hoping to get a simpler file.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;realityComposerExport.png&#34; alt=&#34;Screenshot of Reality Composer export window in context over a view of the file being exported. The radio button for exporting only the scene is selected. USDZ is selected as the export file type in the drop down menu. There are instructions to look up the developer documentation&#34;&gt;&lt;/p&gt;
&lt;p&gt;I now have a file called &lt;code&gt;ThreeBodyUSDZ.usdz&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;I renamed that file to &lt;code&gt;ThreeBodyUSDZ.zip&lt;/code&gt; and extracted the contents (doubled click on it).&lt;/p&gt;
&lt;p&gt;Depending on the complexity of the USDZ, the result will be a .usdc file with a long &lt;code&gt;UUID()&lt;/code&gt;-looking name or a folder that has one in it.  I&amp;rsquo;ll target that file with &lt;code&gt;usdcat&lt;/code&gt; to convert.  &lt;code&gt;usdcat&lt;/code&gt; can work on &lt;code&gt;.usdz&lt;/code&gt; files directly, but the time may come when targeting specific files in an archive will be helpful.&lt;/p&gt;
&lt;h2 id=&#34;step-2-install-the-c-conversion-tool&#34;&gt;Step 2: Install the C++ conversion tool&lt;/h2&gt;
&lt;p&gt;Just doing conversions does not require installing python libraries or modules at all: not from Pixar, nor the ones in &lt;a href=&#34;https://stackoverflow.com/questions/50846627/how-to-create-usdz-file-using-xcode-converter&#34;&gt;USDZ Tools bundle&lt;/a&gt; &lt;a href=&#34;https://developer.apple.com/augmented-reality/tools/&#34;&gt;from Apple&lt;/a&gt;. &lt;code&gt;usdcat&lt;/code&gt;, a utility that lives in the Pixar C++ library on github, will do everything we need.&lt;/p&gt;
&lt;p&gt;That said, we&amp;rsquo;re going to make use of one python script, as Pixar supplies a Python 3.11 compatible build script. (CMake dependency)&lt;/p&gt;
&lt;p&gt;Dependencies for USD itself include: zlib, boost, TBB, MaterialX, OpenSubdiv.  Running the brew install scripts does not appear to appreciably speed things up, the build script appears to go fetch it&amp;rsquo;s own copies regardless.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-zsh&#34; data-lang=&#34;zsh&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# unnecessary, ignored by the compiler, but for the record done&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;brew install zlib
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;brew install boost
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;brew install tbb
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;brew install opensubdiv
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Doing the USD &lt;code&gt;--no-python&lt;/code&gt; install:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-zsh&#34; data-lang=&#34;zsh&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# if haven&amp;#39;t already&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# brew install cmake&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#91d7e3&#34;&gt;cd&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;$DOWNLOAD_DIR&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;git clone https://github.com/PixarAnimationStudios/USD.git
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# there will now be a directory called USD in the pwd&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# the below will show the build options&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;python3 USD/build_scripts/build_usd.py
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# run with the --no-python option&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;python3 USD/build_scripts/build_usd.py --no-python &lt;span style=&#34;color:#f4dbd6&#34;&gt;$BUILD_DEST_DIR&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Fair warning, this takes a long time to run.&lt;/p&gt;
&lt;p&gt;I will not be adding this build to my &lt;code&gt;PATH&lt;/code&gt; at this time. One reason, I am going to make a few different builds and I want it clear in this documentation which one I&amp;rsquo;m using. My &lt;code&gt;$BUILD_DEST_DIR&lt;/code&gt; is &lt;code&gt;~/opb/USDCpp&lt;/code&gt;. &lt;code&gt;opb&lt;/code&gt; &amp;ldquo;off path bin&amp;rdquo; and &lt;code&gt;USDCpp&lt;/code&gt; to let me know I&amp;rsquo;m using the &lt;code&gt;--no-python&lt;/code&gt; build&lt;/p&gt;
&lt;h2 id=&#34;step-3-convert-the-files&#34;&gt;Step 3: Convert the files&lt;/h2&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-zsh&#34; data-lang=&#34;zsh&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# discover options&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;~&lt;span style=&#34;color:#f4dbd6&#34;&gt;$BUILD_DEST_DIR&lt;/span&gt;/usdcat --help
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# The basic pattern:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;~&lt;span style=&#34;color:#f4dbd6&#34;&gt;$BUILD_DEST_DIR&lt;/span&gt;/usdcat -o &lt;span style=&#34;color:#f4dbd6&#34;&gt;$DESTINATION&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;$SOURCE&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# so for example&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#91d7e3&#34;&gt;cd&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;$DIRECTORY_WITH_FILES_TO_CONVERT&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;~/opb/USDCpp/bin/usdcat -o threeBodyExample_fromArchive.usda ThreeBodyUSDZ.usdz
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;~/opb/USDCpp/bin/usdcat -o threeBodyExample_fromCrate.usda ThreeBodyUSDZ/8AE371F7-0528-4095-8AA4-ECDAA71F409E.usdc
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Success!&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;threebodiesusda.png&#34; alt=&#34;Screenshot of same image (rock, cube capsule), but this time in a QuickView window.&#34;&gt;&lt;/p&gt;
&lt;p&gt;All it took was using a destination file name with &lt;code&gt;.usda&lt;/code&gt; as the extension to get a usda file from the conversion tool.&lt;/p&gt;
&lt;h2 id=&#34;step-4-inspect-and-compare-the-files&#34;&gt;Step 4: Inspect and compare the files&lt;/h2&gt;
&lt;p&gt;Helpful hint: use a &lt;a href=&#34;https://github.com/dandavison/delta&#34;&gt;diffing tool&lt;/a&gt; to compare the files. (VSCode: open folder, select files and right click)&lt;/p&gt;
&lt;p&gt;Exactly the same!&lt;/p&gt;
&lt;p&gt;Copies of these files are &lt;a href=&#34;https://github.com/carlynorama/USDHelloWorld/tree/main/explorations/Part_03&#34;&gt;available on GitHub&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Interestingly, changing the extension from .usda to .usd on these files makes them stop working in QuickView. Possible related error messages in &lt;code&gt;Console&lt;/code&gt; (full list from time at &lt;a href=&#34;https://github.com/carlynorama/USDHelloWorld/tree/main/explorations/Part_03/ThreeBodyExample/console_errors_on_usd.txt&#34;&gt;https://github.com/carlynorama/USDHelloWorld/tree/main/explorations/Part_03/ThreeBodyExample/console_errors_on_usd.txt&lt;/a&gt;)&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;WindowServer	CGLayerKit called back with no connection&lt;/li&gt;
&lt;li&gt;kernel	1 duplicate report for System Policy: mds(133) deny(1) file-read-data /private/var/db/searchparty/sharedVault/agents/BADE6C8F-36E9-4FD3-B815-5E34351823AC/savedConfiguration.plist&lt;/li&gt;
&lt;li&gt;kernel	Sandbox: HydraResourceCoordinator(44546) deny(1) file-read-metadata /Users/$USER/Developer/GitHub/USDHelloWorld/Part_03/ThreeBodyExample&lt;/li&gt;
&lt;li&gt;HydraQLPreviewExtension	WARNING: Quick Look extensions should not have any views or subviews claim first responder&lt;/li&gt;
&lt;li&gt;SceneKitQLPreviewExtension	CGSWindowShmemCreateWithPort failed on port 0&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I found the errors interesting but not fully illuminating. I&amp;rsquo;m hoping the USDZ checking script in Apple&amp;rsquo;s USDZ Tools will help, but that&amp;rsquo;s tomorrows topic.&lt;/p&gt;
&lt;p&gt;The stone uses a texture, for the &lt;code&gt;.usda&lt;/code&gt; file to render the texture the image for the texture must have the same relative path to the &lt;code&gt;.usda&lt;/code&gt; as to the original &lt;code&gt;.usdc&lt;/code&gt; or &lt;code&gt;.usdz&lt;/code&gt;, or the &lt;code&gt;.usda&lt;/code&gt; will need to be edited.&lt;/p&gt;
&lt;h2 id=&#34;blender&#34;&gt;Blender&lt;/h2&gt;
&lt;p&gt;Blender appears to export &lt;code&gt;.usdc&lt;/code&gt; files directly, at least for simple projects. These files convert beautifully into &lt;code&gt;.usda&lt;/code&gt; files using &lt;code&gt;usdcat&lt;/code&gt;, and QuickLook can render them fine. Downside, Blender presents a much steeper learning curve than Reality Composer and isn&amp;rsquo;t integrated into the &lt;code&gt;RealityKit&lt;/code&gt; workflow.&lt;/p&gt;
&lt;h2 id=&#34;wrap-up&#34;&gt;Wrap Up&lt;/h2&gt;
&lt;p&gt;It appears the most typical way to create USDZ files is through some GUI: Blender, Reality Composer, Maya, etc. Having a way to convert these software generated files into something human readable makes it easier to learn about the format and was fairly easy to do.&lt;/p&gt;
</description>
    </item>
    
    
    
    <item>
      <title>Hello USD - Part 2: Type the rainbow</title>
      <link>https://whynotestflight.com/excuses/hello-usd-part-2-type-the-rainbow/</link>
      <pubDate>Tue, 27 Jun 2023 00:00:00 +0000</pubDate>
      
      <guid>https://whynotestflight.com/excuses/hello-usd-part-2-type-the-rainbow/</guid>
      <description>&lt;p&gt;As it turns out, the problem &lt;a href=&#34;https://whynotestflight.com/excuses/ooohh-a-new-file-format...-hello-usd-part-1/&#34;&gt;yesterday&lt;/a&gt; with the Blender import will take someone better at Blender than I am to fix. I care about Blender in this context because I was considering it an easy way to get a .x3d file from a .usd file. As it stands I will probably try to find another way to do the conversion.&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s break down what I found. This post references Blender 3.6.0 on an intel Mac.&lt;/p&gt;
&lt;h2 id=&#34;four-ways-of-getting-a-green-cube&#34;&gt;Four ways of getting a green cube&lt;/h2&gt;
&lt;p&gt;I made four files that all work in the Preview ap on MacOS Ventura 13.4. Each either uses an explicitly described mesh or the built in USD &lt;code&gt;Cube&lt;/code&gt; definition. Then each of those model types was paired with either a &lt;code&gt;primvar&lt;/code&gt; color setting or an stand alone &lt;code&gt;Material&lt;/code&gt; definition.&lt;/p&gt;
&lt;table&gt;
  &lt;thead&gt;
      &lt;tr&gt;
          &lt;th&gt;geometry type&lt;/th&gt;
          &lt;th&gt;primvar:displayColor&lt;/th&gt;
          &lt;th&gt;material&lt;/th&gt;
      &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
      &lt;tr&gt;
          &lt;td&gt;Cube type&lt;/td&gt;
          &lt;td&gt;&lt;img src=&#34;1a_primative_primvar.png&#34; alt=&#34;screen shot&#34;&gt;&lt;/td&gt;
          &lt;td&gt;&lt;img src=&#34;1d_primative_material.png&#34; alt=&#34;screen shot&#34;&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;Mesh type&lt;/td&gt;
          &lt;td&gt;&lt;img src=&#34;1b_mesh_primvar.png&#34; alt=&#34;screen shot&#34;&gt;&lt;/td&gt;
          &lt;td&gt;&lt;img src=&#34;1c_mesh_material.png&#34; alt=&#34;screen shot&#34;&gt;&lt;/td&gt;
      &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;The look of the &amp;ldquo;material&amp;rdquo; does not match the color rendering for the &amp;ldquo;displayColor&amp;rdquo; style of color. That&amp;rsquo;s not a surprise and could probably be improved with tweaking. The material on the &lt;code&gt;Cube&lt;/code&gt; prim and the mesh prim does render the same. What does peak my interest is that the displayColor does seem to render differently on the mesh and the &lt;code&gt;Cube&lt;/code&gt;. Hmmm&amp;hellip;&lt;/p&gt;
&lt;p&gt;The USD files for these screen shots are below and in a &lt;a href=&#34;https://github.com/carlynorama/USDHelloWorld/tree/main/explorations/Part_02&#34;&gt;github repo&lt;/a&gt; with other experiments.&lt;/p&gt;
&lt;h2 id=&#34;import-tests-into-blender-results&#34;&gt;Import tests into blender results&lt;/h2&gt;
&lt;p&gt;Only one of the 4 examples actually makes a green cube in Blender.&lt;/p&gt;
&lt;p&gt;Wrinkle one, I mentioned that not all USD implementations support the built in geometry types &lt;a href=&#34;https://openusd.org/release/api/usd_geom_page_front.html&#34;&gt;Sphere, Cube, Cone, etc&lt;/a&gt;. The current import settings on Blender do a fantastic job setting up the mesh on import from the primitives, but the importer seems to loose the plot on other settings, parameters and Materials.&lt;/p&gt;
&lt;p&gt;So while Blender does create from scratch a mesh for the following, it does NOT appear to import any color information into Blender.&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-usd&#34; data-lang=&#34;usd&#34;&gt;#usda 1.0
(
    defaultPrim = &amp;#34;hello&amp;#34;
    upAxis = &amp;#34;Y&amp;#34;
)

def Xform &amp;#34;hello&amp;#34;
{
    def Cube &amp;#34;world&amp;#34;
    {
        float3[] extent = [(-2, -2, -2), (2, 2, 2)]
        color3f[] primvars:displayColor = [(0, 1, 0)]
    }
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The next example will sort of import into Blender (&lt;a href=&#34;https://projects.blender.org/blender/blender/issues/103761&#34;&gt;related issue?&lt;/a&gt;) in that the color will appear in the mesh&amp;rsquo;s Color Attributes window as a vertex color, but it doesn&amp;rsquo;t actually seem to show anywhere in any of the different display modes? I know very little about Blender. This could be a crazy easy fix, but I don&amp;rsquo;t know how to do it.&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-usd&#34; data-lang=&#34;usd&#34;&gt;#usda 1.0
(
    defaultPrim = &amp;#34;Cube&amp;#34;
    upAxis = &amp;#34;Y&amp;#34;
)


def Xform &amp;#34;Cube&amp;#34;
{
    def Mesh &amp;#34;cubeMesh&amp;#34;
    { 
        float3[] extent = [(-2, -2, -2), (2, 2, 2)]
        int[] faceVertexCounts = [4, 4, 4, 4, 4, 4]
        int[] faceVertexIndices = [0, 1, 2, 3, 4, 5, 6, 7, 0, 6, 5, 1, 4, 7, 3, 2, 0, 3, 7, 6, 4, 2, 1, 5]
        point3f[] points = [(1, 1, 1), (-1, 1, 1), (-1, -1, 1), (1, -1, 1), (-1, -1, -1), (-1, 1, -1), (1, 1, -1), (1, -1, -1)]
        color3f[] primvars:displayColor = [(0, 1, 0)]
    }
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;What does work? Adding an explicit material to a MESH. Using the &lt;code&gt;Cube&lt;/code&gt; won&amp;rsquo;t work.&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-usd&#34; data-lang=&#34;usd&#34;&gt;#usda 1.0
(
    defaultPrim = &amp;#34;Cube&amp;#34;
    upAxis = &amp;#34;Y&amp;#34;
)


def Xform &amp;#34;Cube&amp;#34;
{
    def Mesh &amp;#34;cubeMesh&amp;#34;
    {
        float3[] extent = [(-2, -2, -2), (2, 2, 2)]
        int[] faceVertexCounts = [4, 4, 4, 4, 4, 4]
        int[] faceVertexIndices = [0, 1, 2, 3,   4, 5, 6, 7,   0, 6, 5, 1, 
                                   4, 7, 3, 2,   0, 3, 7, 6,   4, 2, 1, 5]
        point3f[] points = [(1, 1, 1), (-1, 1, 1), (-1, -1, 1), (1, -1, 1), (-1, -1, -1), (-1, 1, -1), (1, 1, -1), (1, -1, -1)]
        uniform token subdivisionScheme = &amp;#34;none&amp;#34;
        rel material:binding = &amp;lt;/myFlatGreen&amp;gt;
    }
}


def Material &amp;#34;myFlatGreen&amp;#34;
    {
        token outputs:surface.connect = &amp;lt;/myFlatGreen/PBRShader.outputs:surface&amp;gt;
        
        def Shader &amp;#34;PBRShader&amp;#34;
        {
            uniform token info:id = &amp;#34;UsdPreviewSurface&amp;#34;
            color3f inputs:diffuseColor = (0, 1, 0)
            color3f inputs:emissiveColor = (0, 1, 0)
            float inputs:metallic = 0
            float inputs:roughness = 0.5
            int inputs:useSpecularWorkflow = 0
            token outputs:surface
        }
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Hello green cube in x3d. (&lt;a href=&#34;green_cube.x3d&#34;&gt;raw file&lt;/a&gt;)&lt;/p&gt;
&lt;script type=&#39;text/javascript&#39; src=&#39;https://www.x3dom.org/download/x3dom.js&#39;&gt; &lt;/script&gt; 
&lt;x3d width=&#39;500px&#39; height=&#39;400px&#39;&gt; 
&lt;scene&gt;
&lt;inline url=&#34;green_cube.x3d&#34;&gt; &lt;/inline&gt; 
&lt;/scene&gt; 
&lt;/x3d&gt;  
&lt;h2 id=&#34;so-what-did-we-learn-today&#34;&gt;So what did we learn today?&lt;/h2&gt;
&lt;h3 id=&#34;meshes&#34;&gt;Meshes&lt;/h3&gt;
&lt;p&gt;Geometries in USD files can be described as meshes, points, nurbs, curves&amp;hellip; &lt;a href=&#34;https://openusd.org/release/api/usd_geom_page_front.html&#34;&gt;lots of options&lt;/a&gt;. In this case we went from UsdGeomCube to a UsdGeomMesh.&lt;/p&gt;
&lt;p&gt;A mesh, to pull from the definition in the &lt;a href=&#34;https://openusd.org/release/api/class_usd_geom_mesh.html&#34;&gt;USD docs&lt;/a&gt;, is &amp;ldquo;a point-based primitive&amp;hellip; defined in terms of points that are connected into edges and faces.&amp;rdquo;&lt;/p&gt;
&lt;p&gt;Describing a Cube&amp;rsquo;s mesh characteristics in terms of USD specs:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;First we leave the &lt;code&gt;extent&lt;/code&gt; as is to match the &lt;code&gt;Cube&lt;/code&gt; type&amp;rsquo;s behavior (this prevented clipping in the viewer, try switching the &lt;code&gt;extent&lt;/code&gt; to 1&amp;rsquo;s to see the difference, as the cube turns the corners will go &amp;ldquo;behind&amp;rdquo; the camera.).&lt;/li&gt;
&lt;li&gt;A cube has 6 faces, each with 4 corners. =&amp;gt; &lt;code&gt;int[] faceVertexCounts = [4, 4, 4, 4, 4, 4]&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;A cube has 8 corners total, our cube will be from (1, 1, 1) to (-1, -1, -1) =&amp;gt; &lt;code&gt;point3f[] points = [(1, 1, 1), (-1, 1, 1), (-1, -1, 1), (1, -1, 1), (-1, -1, -1), (-1, 1, -1), (1, 1, -1), (1, -1, -1)]&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Each face can be described as indexes into the point array. If its correct each index should be used 3 times (each of the faces it touches) =&amp;gt; &lt;code&gt;int[] faceVertexIndices = [0, 1, 2, 3, 4, 5, 6, 7, 0, 6, 5, 1, 4, 7, 3, 2, 0, 3, 7, 6, 4, 2, 1, 5]&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Additionally one could describe the normals of the faces or corners, but in this simple cube case that doesn&amp;rsquo;t seem to be needed by either the Preview quick look or the Blender import. There also seems to be &lt;a href=&#34;https://github.com/PixarAnimationStudios/OpenUSD/issues/706&#34;&gt;some debate&lt;/a&gt; as to whether one should use the schema definition i.e. do &lt;code&gt;normal3f[] normals = [..]&lt;/code&gt; or add it as an indexable primvar, i.e. &lt;code&gt;normal3f[] normals primvars:normals = [..]&lt;/code&gt; which is how Apple generated USD files also do it. (more on that tomorrow)&lt;/p&gt;
&lt;h3 id=&#34;a-little-more-on-primvars&#34;&gt;A little more on primvars&lt;/h3&gt;
&lt;p&gt;Both of the following make a glorious rainbow colored cube.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;rainbow_cube.png&#34; alt=&#34;rainbow colored cube in screen shot window&#34;&gt;&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;#usda 1.0

def Xform &amp;#34;Rainbow&amp;#34;
{

    def Mesh &amp;#34;cubeMesh&amp;#34;
    {
        float3[] extent = [(-2, -2, -2), (2, 2, 2)]
        int[] faceVertexCounts = [4, 4, 4, 4, 4, 4]
        int[] faceVertexIndices = [0, 1, 2, 3, 4, 5, 6, 7, 0, 6, 5, 1, 4, 7, 3, 2, 0, 3, 7, 6, 4, 2, 1, 5]
        point3f[] points = [(1, 1, 1), (-1, 1, 1), (-1, -1, 1), (1, -1, 1), (-1, -1, -1), (-1, 1, -1), (1, 1, -1), (1, -1, -1)]
        color3f[] primvars:displayColor = [(0, 0, 1), (1,0,1), (1,0,0), (0, 1, 0),(0, 0, 1), (1,0,1), (1,0,0), (0, 1, 0)](
          interpolation = &amp;#34;vertex&amp;#34;
        )
        uniform token subdivisionScheme = &amp;#34;none&amp;#34;
    }
}
&lt;/code&gt;&lt;/pre&gt;&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;#usda 1.0

def Xform &amp;#34;Rainbow&amp;#34;
{

    def Cube &amp;#34;cube&amp;#34;
    {
        float3[] extent = [(-2, -2, -2), (2, 2, 2)]
         color3f[] primvars:displayColor = [(0, 0, 1), (1,0,1), (1,0,0), (0, 1, 0),(0, 0, 1), (1,0,1), (1,0,0), (0, 1, 0)](
          interpolation = &amp;#34;vertex&amp;#34;
        )
    }
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Lets look at this description of primvars from Pixar&amp;rsquo;s old RenderMan documentation:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Primitive Variables (also known as primvars) are data stored on objects.  This data can be used for shading variation, much like user attributes.  There are two main distinctions between the two - primvars cannot vary across instances, but they allow more specific variation - constant, uniform, varying, vertex, and facevarying.&lt;/p&gt;&lt;/blockquote&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://rmanwiki.pixar.com/display/RFK24/Primitive+Variables&#34;&gt;https://rmanwiki.pixar.com/display/RFK24/Primitive+Variables&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The rainbow cube uses &amp;ldquo;vertex&amp;rdquo; interpolations with an array of colors defined in primvars, the type of process which can also be used to create heat maps, etc. (&lt;a href=&#34;https://www.youtube.com/watch?v=ps5wBt04Ayg&#34;&gt;example using Omniverse&lt;/a&gt;)&lt;/p&gt;
&lt;p&gt;&amp;ldquo;st&amp;rdquo; seems to be another common primvar set used for&amp;hellip; something&amp;hellip; related to &amp;ldquo;uv&amp;rdquo;??? It will all become clear at some point.&lt;/p&gt;
&lt;p&gt;Also a useful read &lt;a href=&#34;https://www.sidefx.com/docs/houdini/solaris/usd.html#attrs&#34;&gt;https://www.sidefx.com/docs/houdini/solaris/usd.html#attrs&lt;/a&gt;&lt;/p&gt;
&lt;h3 id=&#34;attaching-materials-to-shapes&#34;&gt;Attaching Materials to Shapes&lt;/h3&gt;
&lt;p&gt;Recommended Reading:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://openusd.org/release/api/class_usd_shade_material.html#details&#34;&gt;https://openusd.org/release/api/class_usd_shade_material.html#details&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://openusd.org/release/wp_usdshade.html&#34;&gt;https://openusd.org/release/wp_usdshade.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://openusd.org/release/glossary.html#usdglossary-connection&#34;&gt;https://openusd.org/release/glossary.html#usdglossary-connection&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;After tomorrow: &lt;a href=&#34;https://openusd.org/release/tut_simple_shading.html&#34;&gt;https://openusd.org/release/tut_simple_shading.html&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&#34;step-1-create-the-material-description&#34;&gt;Step 1: Create the Material description.&lt;/h4&gt;
&lt;p&gt;Lets look at the Material description from the green cubes. I pulled the bones of this from out of an Apple Reality Composer usdz file export.  How to do that is tomorrow&amp;rsquo;s topic.&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;def Material &amp;#34;myFlatGreen&amp;#34;
    {
        token outputs:surface.connect = &amp;lt;/myFlatGreen/PBRShader.outputs:surface&amp;gt;
        
        def Shader &amp;#34;PBRShader&amp;#34;
        {
            uniform token info:id = &amp;#34;UsdPreviewSurface&amp;#34;
            color3f inputs:diffuseColor = (0, 1, 0)
            color3f inputs:emissiveColor = (0, 1, 0)
            float inputs:metallic = 0
            float inputs:roughness = 0.5
            int inputs:useSpecularWorkflow = 0
            token outputs:surface
        }
}
&lt;/code&gt;&lt;/pre&gt;&lt;ul&gt;
&lt;li&gt;&lt;code&gt;def Material&lt;/code&gt; we are defining a &lt;a href=&#34;https://openusd.org/release/api/class_usd_shade_material.html&#34;&gt;UsdShadeMaterial&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;token outputs:surface.connect&lt;/code&gt; a &lt;a href=&#34;https://openusd.org/release/glossary.html#usdglossary-connection&#34;&gt;connection type&lt;/a&gt; connects the Shader&amp;rsquo;s output attribute to the materials output attribute.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;def Shader&lt;/code&gt; we are defining the &lt;a href=&#34;https://openusd.org/release/api/class_usd_shade_shader.html&#34;&gt;UsdShadeShader&lt;/a&gt; different renderers might draw upon different Shaders for the same Material, for example.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;uniform token info:id = &amp;quot;UsdPreviewSurface&amp;quot;&lt;/code&gt; &lt;a href=&#34;https://openusd.org/release/spec_usdpreviewsurface.html&#34;&gt;UsdPreviewSurface&lt;/a&gt; A promise that this surface is simple enough to use in most applications. It&amp;rsquo;s a &amp;ldquo;a more flexible, non-ubersurface, style of describing surfaces&amp;rdquo;. This texture will work for both &amp;ldquo;metallic&amp;rdquo; and &amp;ldquo;specular&amp;rdquo; workflows. (&lt;a href=&#34;https://www.youtube.com/watch?v=mrNMpqdNchY&#34;&gt;excellent 5 min video on those 2 terms&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Every item after that is either and input or output for our UsdPreviewSurface and is documented here: &lt;a href=&#34;https://openusd.org/release/spec_usdpreviewsurface.html&#34;&gt;https://openusd.org/release/spec_usdpreviewsurface.html&lt;/a&gt; (same link as above.)&lt;/p&gt;
&lt;h4 id=&#34;step-2-link-the-material&#34;&gt;Step 2: Link the Material&lt;/h4&gt;
&lt;p&gt;There doesn&amp;rsquo;t seem to be one answer as to where one should create a Material. When looking into why Blender wasn&amp;rsquo;t importing the Material on my files I tried &lt;a href=&#34;https://github.com/carlynorama/USDHelloWorld/tree/main/explorations/Part_02/ways_to_attach_a_material&#34;&gt;SEVERAL methods&lt;/a&gt;, all of which work in Preview.&lt;/p&gt;
&lt;p&gt;Some people create a file for all their materials, some people put the material in their primitive. It depends on your project&amp;rsquo;s organization.&lt;/p&gt;
&lt;p&gt;Wherever it lives, it will have a location path to create the &lt;a href=&#34;https://openusd.org/release/glossary.html#usdglossary-relationship&#34;&gt;relationship&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Take the example below. It has a catalog of colors that then &amp;ldquo;MyCube&amp;rdquo; makes variants of. Switching the variant name in the &amp;ldquo;MyCube&amp;rdquo; definition will switch the color in the viewer.&lt;/p&gt;
&lt;table&gt;
  &lt;thead&gt;
      &lt;tr&gt;
          &lt;th&gt;myFlatGreen&lt;/th&gt;
          &lt;th&gt;exportedBlenderPurple&lt;/th&gt;
          &lt;th&gt;exportedApplePurple&lt;/th&gt;
      &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;img src=&#34;green.png&#34; alt=&#34;screen shot&#34;&gt;&lt;/td&gt;
          &lt;td&gt;&lt;img src=&#34;purple_01.png&#34; alt=&#34;screen shot&#34;&gt;&lt;/td&gt;
          &lt;td&gt;&lt;img src=&#34;purple_02.png&#34; alt=&#34;screen shot&#34;&gt;&lt;/td&gt;
      &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-usd&#34; data-lang=&#34;usd&#34;&gt;#usda 1.0
(
    defaultPrim = &amp;#34;MyCube&amp;#34;
    upAxis = &amp;#34;Y&amp;#34;
)

def Xform &amp;#34;MyCube&amp;#34; 
(
    variants = {
        string shadingVariant = &amp;#34;purple_01&amp;#34;
    }
    prepend variantSets = &amp;#34;shadingVariant&amp;#34;
)
{
    def Mesh &amp;#34;cubeMesh&amp;#34;
    {   
        rel material:binding
        float3[] extent = [(-2, -2, -2), (2, 2, 2)]
        int[] faceVertexCounts = [4, 4, 4, 4, 4, 4]
        int[] faceVertexIndices = [0, 1, 2, 3, 4, 5, 6, 7, 0, 6, 5, 1, 4, 7, 3, 2, 0, 3, 7, 6, 4, 2, 1, 5]
        point3f[] points = [(1, 1, 1), (-1, 1, 1), (-1, -1, 1), (1, -1, 1), (-1, -1, -1), (-1, 1, -1), (1, 1, -1), (1, -1, -1)]
        uniform token subdivisionScheme = &amp;#34;none&amp;#34;
    }
 
    variantSet &amp;#34;shadingVariant&amp;#34; = {
        &amp;#34;purple_01&amp;#34; {
            over &amp;#34;cubeMesh&amp;#34;
            {
                rel material:binding = &amp;lt;/SolidColorMaterials/exportedBlenderPurple&amp;gt;
            }
        }

        &amp;#34;green&amp;#34; {
            over &amp;#34;cubeMesh&amp;#34;
            {
                rel material:binding = &amp;lt;/SolidColorMaterials/myFlatGreen&amp;gt;
            }
        }

        &amp;#34;purple_02&amp;#34; {
            over &amp;#34;cubeMesh&amp;#34;
            {
                rel material:binding = &amp;lt;/SolidColorMaterials/exportedApplePurple&amp;gt;
            }
        }
    }
}


def Scope &amp;#34;SolidColorMaterials&amp;#34;
{
    def Material &amp;#34;myFlatGreen&amp;#34;
        {
            token outputs:surface.connect = &amp;lt;/SolidColorMaterials/myFlatGreen/PBRShader.outputs:surface&amp;gt;
            
            def Shader &amp;#34;PBRShader&amp;#34;
            {
                uniform token info:id = &amp;#34;UsdPreviewSurface&amp;#34;
                color3f inputs:diffuseColor = (0, 1, 0)
                color3f inputs:emissiveColor = (0, 1, 0)
                float inputs:metallic = 0
                float inputs:roughness = 0.5
                int inputs:useSpecularWorkflow = 0
                token outputs:surface
            }
    }

    def Material &amp;#34;exportedBlenderPurple&amp;#34;
    {
        token outputs:surface.connect = &amp;lt;/SolidColorMaterials/exportedBlenderPurple/previewShader.outputs:surface&amp;gt;

        def Shader &amp;#34;previewShader&amp;#34;
        {
            uniform token info:id = &amp;#34;UsdPreviewSurface&amp;#34;
            color3f inputs:diffuseColor = (0.8000001, 0.1429553, 0.52986294)
            float inputs:metallic = 0.2
            float inputs:roughness = 0.4
            token outputs:surface
        }
    }

    def Material &amp;#34;exportedApplePurple&amp;#34;
    {
        token outputs:surface.connect = &amp;lt;/SolidColorMaterials/exportedApplePurple/PBRShader.outputs:surface&amp;gt;

        def Shader &amp;#34;PBRShader&amp;#34;
        {
            uniform token info:id = &amp;#34;UsdPreviewSurface&amp;#34;
            color3f inputs:diffuseColor = (0.31854683, 0.033104762, 1)
            color3f inputs:emissiveColor = (0, 0, 0)
            float inputs:metallic = 0
            float inputs:roughness = 0.55
            int inputs:useSpecularWorkflow = 0
            token outputs:surface
        }
    }
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Full disclosure, I tried and failed to create a stage with all three variants on it last night. The cubes were there, but the materials were not.&lt;/p&gt;
&lt;p&gt;To figure out how to do better I need to use some of the tools I&amp;rsquo;ve been quietly using all along. Tomorrow&amp;rsquo;s post will be all about installing the existing (non-Beta) python, C++ and XCode command-line tools.&lt;/p&gt;
</description>
    </item>
    
    
    
    <item>
      <title>OOohh a new file format... Hello USD - Part 1</title>
      <link>https://whynotestflight.com/excuses/ooohh-a-new-file-format...-hello-usd-part-1/</link>
      <pubDate>Tue, 27 Jun 2023 00:00:00 +0000</pubDate>
      
      <guid>https://whynotestflight.com/excuses/ooohh-a-new-file-format...-hello-usd-part-1/</guid>
      <description>&lt;p&gt;The cross platform open source file format &lt;a href=&#34;https://openusd.org/&#34;&gt;OpenUSD&lt;/a&gt; (previously Pixar Universal Scene Description) backs the immersive experiences in Apple&amp;rsquo;s VisionOS. For most people and teams it will be largely hidden from view by RealityComposer and now its successor RealityComposerPro. That said even without installing any 2023 beta software, Apple&amp;rsquo;s Preview already displays USD files. Apple has been working with the film industry to accommodate existing software and pipelines for years, apparently.&lt;/p&gt;
&lt;p&gt;Part one is the structure of a basic USD file describing a collection of spheres. It assumes you know python and have done some graphics programming before. Later sections will assume comfort around C, C++ and Swift.&lt;/p&gt;
&lt;h2 id=&#34;references&#34;&gt;References&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Understand USD Fundamentals, WWDC22, &lt;a href=&#34;https://developer.apple.com/videos/play/wwdc2022/10129/&#34;&gt;https://developer.apple.com/videos/play/wwdc2022/10129/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://openusd.org/release/index.html&#34;&gt;https://openusd.org/release/index.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/PixarAnimationStudios/OpenUSD&#34;&gt;https://github.com/PixarAnimationStudios/OpenUSD&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;whats-a-usd-file&#34;&gt;What&amp;rsquo;s a USD file?&lt;/h2&gt;
&lt;p&gt;OpenUSD files aren&amp;rsquo;t simply 3D object models. USD provides a language to describe &amp;ldquo;scenes&amp;rdquo;: all the objects, positioning, animations, etc. There are multiple extensions for working with OpenUSD files, one of which is explicitly a package.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;.usda&lt;/code&gt; which is an ascii encoded usd file that represents usd information in human readable format&lt;/li&gt;
&lt;li&gt;&lt;code&gt;.usdc&lt;/code&gt; which is optimized for machine readability since usd files can be quite large&lt;/li&gt;
&lt;li&gt;&lt;code&gt;.usd&lt;/code&gt; which could be either of the previous 2 under the hood.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;.usdz&lt;/code&gt; a zip file of multiple usd files and assets.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;getting-started&#34;&gt;Getting Started&lt;/h2&gt;
&lt;p&gt;Pixar has made available &lt;a href=&#34;https://github.com/PixarAnimationStudios/OpenUSD&#34;&gt;C++ and Python code&lt;/a&gt; that enables folks to work with USD files, but compiling it isn&amp;rsquo;t necessary for a Hello World because of the &amp;ldquo;human readable&amp;rdquo; ASCII version of the spec. Put the below in a text file with the extension &lt;code&gt;.usd&lt;/code&gt; and Preview will open it. I&amp;rsquo;ve called mine the super imaginative &lt;code&gt;sphere.usd&lt;/code&gt;. I am using the &lt;code&gt;usd&lt;/code&gt; extension instead of the &lt;code&gt;usda&lt;/code&gt; extension so Preview will open it.&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-usd&#34; data-lang=&#34;usd&#34;&gt;#usda 1.0
# https://openusd.org/release/tut_helloworld_redux.html

def Sphere &amp;#34;sphere&amp;#34;
{
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;img src=&#34;01_basicsphere.png&#34; alt=&#34;A low poly image of a gray sphere in a computer window.&#34;&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Sphere&lt;/code&gt; is a built in geometry primitive on &lt;a href=&#34;https://openusd.org/release/api/usd_geom_page_front.html&#34;&gt;many but not all&lt;/a&gt; implementations of OpenUSD. Primitives or &amp;ldquo;prims&amp;rdquo; refer to scene elements on a stage. A more complete .usd file for a sphere would look something like:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-usd&#34; data-lang=&#34;usd&#34;&gt;#usda 1.0
# https://openusd.org/release/tut_inspect_and_author_props.html

def Xform &amp;#34;hello&amp;#34;
{
    def Sphere &amp;#34;world&amp;#34;
    {
        float3[] extent = [(-2, -2, -2), (2, 2, 2)]
        color3f[] primvars:displayColor = [(0, 0, 1)]
        double radius = 2
    }
}
&lt;/code&gt;&lt;/pre&gt;&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://openusd.org/dev/api/class_usd_geom_xform.html&#34;&gt;&lt;code&gt;Xform&lt;/code&gt;&lt;/a&gt; tells us we are inheriting from a &amp;ldquo;transformable&amp;rdquo; class. In this case a &lt;code&gt;UsdGeomXform&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://openusd.org/dev/api/struct_usd_geom_tokens_type.html#ac39bcc5602bc2d6f277d53c366e7e569&#34;&gt;&lt;code&gt;extent&lt;/code&gt;&lt;/a&gt; is an array of float3 to describe the size of the object. It is available on &lt;code&gt;UsdGeomBoundable&lt;/code&gt;, &lt;code&gt;UsdGeomCube&lt;/code&gt;, &lt;code&gt;UsdGeomSphere&lt;/code&gt;, &lt;code&gt;UsdGeomCylinder&lt;/code&gt;, &lt;code&gt;UsdGeomCapsule&lt;/code&gt;, &lt;code&gt;UsdGeomCone&lt;/code&gt;, &lt;code&gt;UsdGeomPlane&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;[&lt;code&gt;primvars:displayColor&lt;/code&gt;] primvars is essentially like a struct that holds the settings for the primitive. Most tutorials don&amp;rsquo;t cover how to hand code USD files. I have not found a comprehensive list of available settings, because likely what variables are available depend on which classes your prim is inheriting from.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src=&#34;02_bluesphere.png&#34; alt=&#34;A low poly image of a bright blue sphere in a computer window.&#34;&gt;&lt;/p&gt;
&lt;h2 id=&#34;two-to-tango&#34;&gt;Two to Tango&lt;/h2&gt;
&lt;p&gt;What if you want two spheres? The original geometry primitive can be reused in an entirely different file with what is referred to as &amp;ldquo;layers&amp;rdquo;, although that word appears nowhere in the file itself. Layers don&amp;rsquo;t alter the underlying file, they override it. There seems to be some analogies with CSS in terms of which files/options get rendering priority in case of conflict. Our scene isn&amp;rsquo;t that complicated yet.&lt;/p&gt;
&lt;h3 id=&#34;the-base-file&#34;&gt;The base file&lt;/h3&gt;
&lt;p&gt;First, create a &lt;code&gt;base_sphere.usd&lt;/code&gt; file which takes our sphere file and adds a new default position to it, an offset from the center. There are a handful of tokens one can &lt;a href=&#34;https://openusd.org/dev/api/class_usd_geom_xform_common_a_p_i.html&#34;&gt;set on a geometric primitive easily&lt;/a&gt; it appears.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;inversePivot&lt;/li&gt;
&lt;li&gt;pivot&lt;/li&gt;
&lt;li&gt;rotate&lt;/li&gt;
&lt;li&gt;scale&lt;/li&gt;
&lt;li&gt;translate&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;A much larger number of tokens is listed if you look at the &lt;a href=&#34;https://openusd.org/dev/api/usd_2usd_geom_2tokens_8h_source.html&#34;&gt;header file&lt;/a&gt;, but translate, pivot and rotate aren&amp;rsquo;t on that list?&lt;/p&gt;
&lt;p&gt;TODO: What&amp;rsquo;s the deal with tokens vs primvars.&lt;/p&gt;
&lt;p&gt;It looks like the format is such that one sets the value, and then passes the value name as a string to an array that determines what order the various possible alterations are applied. Fascinating. I&amp;rsquo;m going to have to look at the parser. No wonder they don&amp;rsquo;t want people hand scripting this. FWIW, The python API to write this couplet is &lt;code&gt;UsdGeom.XformCommonAPI(hello).SetTranslate((4, 5, 6))&lt;/code&gt; so it isn&amp;rsquo;t a string under the hood? To be continued after we install the package&amp;hellip;&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-usd&#34; data-lang=&#34;usd&#34;&gt;#usda 1.0
# https://openusd.org/release/tut_referencing_layers.html
(
    defaultPrim = &amp;#34;hello&amp;#34;
)

def Xform &amp;#34;hello&amp;#34;
{
    double3 xformOp:translate = (4, 5, 6) 
    uniform token[] xformOpOrder = [&amp;#34;xformOp:translate&amp;#34;]

    def Sphere &amp;#34;world&amp;#34;
    {
        float3[] extent = [(-2, -2, -2), (2, 2, 2)]
        color3f[] primvars:displayColor = [(0, 0, 1)]
        double radius = 2
    }
}
&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=&#34;the-layers-file&#34;&gt;The layers file&lt;/h3&gt;
&lt;p&gt;Next, write a file that uses our Sphere definition and overwrites the properties on it as desired.&lt;/p&gt;
&lt;p&gt;In the below file for the layers (I&amp;rsquo;ll refer to it as &lt;code&gt;sphere_layers.usd&lt;/code&gt;)&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&amp;ldquo;blueSphere&amp;rdquo; wipes out the tokens by setting the array to empty, but leaves the primvars and other setting alone. We expect it to be blue and at the origin.&lt;/li&gt;
&lt;li&gt;&amp;ldquo;redSphere&amp;rdquo; leaves the tokens array, but overwrites the color. We expect it to be offset, red and bigger.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-usd&#34; data-lang=&#34;usd&#34;&gt;#usda 1.0
# https://openusd.org/release/tut_referencing_layers.html

over &amp;#34;blueSphere&amp;#34; (
    prepend references = @./base_sphere.usd@
)
{
    uniform token[] xformOpOrder = []
}

over &amp;#34;redSphere&amp;#34; (
    prepend references = @./base_sphere.usd@
)
{
    over &amp;#34;world&amp;#34;
    {
        color3f[] primvars:displayColor = [(1, 0, 0)]
        double radius = 3
    }
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;img src=&#34;03_twospheres.png&#34; alt=&#34;A low poly image of a bright blue sphere and a bright red sphere somewhat separated, in a computer window.&#34;&gt;&lt;/p&gt;
&lt;h2 id=&#34;all-the-spheres&#34;&gt;All the spheres!!!&lt;/h2&gt;
&lt;p&gt;What if you want a lot of spheres? The below script generates a usd file with multiple spheres, with random colors.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;04_multispheres.png&#34; alt=&#34;A bunch of spheres glommed together. Each is a slightly different size and color.&#34;&gt;&lt;/p&gt;
&lt;p&gt;Example usage:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;python3 multiball.py 30 myspheres&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Where &lt;code&gt;30&lt;/code&gt; is the number of spheres and &lt;code&gt;myspheres&lt;/code&gt; is the name of the output file. The arguments are optional.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#5b6078;font-style:italic&#34;&gt;#!/usr/bin/env python3&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8bd5ca&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;sys&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8bd5ca&#34;&gt;from&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;datetime&lt;/span&gt; &lt;span style=&#34;color:#8bd5ca&#34;&gt;import&lt;/span&gt; datetime
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8bd5ca&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;random&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;minX &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;-&lt;/span&gt;&lt;span style=&#34;color:#f5a97f&#34;&gt;4.0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;maxX &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;4.0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;minY &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; minX
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;maxY &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; maxX
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;minZ &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; minX
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;maxZ &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; maxX
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;minRadius &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;0.8&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;maxRadius &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;2.0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;file_header&lt;/span&gt;(): 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#39;#usda 1.0&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\n&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;offset_string&lt;/span&gt;(xoffset, yoffset, zoffset):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#&amp;#34;My name is {fname}, I&amp;#39;m {age}&amp;#34;.format(fname = &amp;#34;John&amp;#34;, age = 36)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\n\t&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;double3 xformOp:translate = (&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;{x}&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;, &lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;{y}&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;, &lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;{z}&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\n\t&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;uniform token[] xformOpOrder = [&amp;#34;xformOp:translate&amp;#34;]&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\n&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;.&lt;/span&gt;format(x&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt;xoffset, y&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt;yoffset, z&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt;zoffset)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;color_string&lt;/span&gt;(red, green, blue):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\n\t\t&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;color3f[] primvars:displayColor = [(&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;{r}&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;, &lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;{g}&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;, &lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;{b}&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;)]&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;.&lt;/span&gt;format(r&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt;red, g&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt;green, b&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt;blue)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;radius_string&lt;/span&gt;(radius):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\n\t\t&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;double radius = &lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;{rad}&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;.&lt;/span&gt;format(rad &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; radius)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;build_item&lt;/span&gt;(&lt;span style=&#34;color:#91d7e3&#34;&gt;id&lt;/span&gt;, reference_file, geometry_name, xoffset, yoffset, zoffset, radius, red, green, blue):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    tmp_string &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\n&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;over &amp;#34;&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;+&lt;/span&gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;id&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;+&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#39;&amp;#34; (&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\n\t&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;prepend references = @./&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;+&lt;/span&gt; reference_file &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;+&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#39;.usd@&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\n&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\n&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;{&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;any&lt;/span&gt;([xoffset &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;!=&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;0&lt;/span&gt;, yoffset &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;!=&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;0&lt;/span&gt;, zoffset &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;!=&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;0&lt;/span&gt;]):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        tmp_string &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; tmp_string &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;+&lt;/span&gt; offset_string(xoffset, yoffset, zoffset)        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    tmp_string &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; tmp_string &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;+&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\n\t&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;over &amp;#34;&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;+&lt;/span&gt; geometry_name &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;+&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#39;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\n\t&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;{&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    tmp_string &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; tmp_string &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;+&lt;/span&gt; color_string(red, green, blue)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    tmp_string &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; tmp_string &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;+&lt;/span&gt; radius_string(radius)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    tmp_string &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; tmp_string &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;+&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\n\t&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;}&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    tmp_string &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; tmp_string &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;+&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\n&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;}&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; tmp_string
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;write_file&lt;/span&gt;(string, path):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;with&lt;/span&gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;open&lt;/span&gt;(path, &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#39;bw+&amp;#39;&lt;/span&gt;) &lt;span style=&#34;color:#c6a0f6&#34;&gt;as&lt;/span&gt; f:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        f&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;.&lt;/span&gt;write(string&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;.&lt;/span&gt;encode(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#39;utf-8&amp;#39;&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        f&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;.&lt;/span&gt;close()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;__name__&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;==&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;__main__&amp;#34;&lt;/span&gt;:    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;len&lt;/span&gt;(sys&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;.&lt;/span&gt;argv) &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;==&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;3&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        count &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;int&lt;/span&gt;(sys&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;.&lt;/span&gt;argv[&lt;span style=&#34;color:#f5a97f&#34;&gt;1&lt;/span&gt;])
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        destination_file_name &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; sys&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;.&lt;/span&gt;argv[&lt;span style=&#34;color:#f5a97f&#34;&gt;2&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;elif&lt;/span&gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;len&lt;/span&gt;(sys&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;.&lt;/span&gt;argv) &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;==&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;2&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        count &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;int&lt;/span&gt;(sys&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;.&lt;/span&gt;argv[&lt;span style=&#34;color:#f5a97f&#34;&gt;1&lt;/span&gt;])
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        destination_file_name &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;multiball_&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;+&lt;/span&gt; datetime&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;.&lt;/span&gt;now()&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;.&lt;/span&gt;strftime(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;%Y%m&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;%d&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;T%H%M%S&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;else&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        count &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;5&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        destination_file_name &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;multiball_&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;+&lt;/span&gt; datetime&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;.&lt;/span&gt;now()&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;.&lt;/span&gt;strftime(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;%Y%m&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;%d&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;T%H%M%S&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    origin_marker &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; build_item(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;blueSphere&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;sphere_base&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;sphere&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#f5a97f&#34;&gt;0&lt;/span&gt;, &lt;span style=&#34;color:#f5a97f&#34;&gt;0&lt;/span&gt;, &lt;span style=&#34;color:#f5a97f&#34;&gt;0&lt;/span&gt;, &lt;span style=&#34;color:#f5a97f&#34;&gt;1&lt;/span&gt;, &lt;span style=&#34;color:#f5a97f&#34;&gt;0&lt;/span&gt;, &lt;span style=&#34;color:#f5a97f&#34;&gt;0&lt;/span&gt;, &lt;span style=&#34;color:#f5a97f&#34;&gt;1&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    file_contents &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; file_header() &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;+&lt;/span&gt; origin_marker
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;for&lt;/span&gt; x &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;in&lt;/span&gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;range&lt;/span&gt;(count):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        file_contents &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; file_contents &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;+&lt;/span&gt; build_item(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;sphere_&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;+&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;{id}&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;.&lt;/span&gt;format(&lt;span style=&#34;color:#91d7e3&#34;&gt;id&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt;x), &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;sphere_base&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;sphere&amp;#34;&lt;/span&gt;, random&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;.&lt;/span&gt;uniform(minX, maxX), random&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;.&lt;/span&gt;uniform(minY, maxY), random&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;.&lt;/span&gt;uniform(minZ, maxZ), random&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;.&lt;/span&gt;uniform(minRadius, maxRadius), random&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;.&lt;/span&gt;random(), random&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;.&lt;/span&gt;random(), random&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;.&lt;/span&gt;random())
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(file_contents)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    write_file(file_contents, destination_file_name &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;+&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;.usd&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Using the following sphere_base.usd file:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;#usda 1.0
(
    defaultPrim = &amp;#34;my_shape&amp;#34;
)

def Xform &amp;#34;my_shape&amp;#34;
{
    double3 xformOp:translate = (0, 0, 0)
    uniform token[] xformOpOrder = [&amp;#34;xformOp:translate&amp;#34;]

    def Sphere &amp;#34;sphere&amp;#34;
    {
        float3[] extent = [(-2, -2, -2), (2, 2, 2)]
        color3f[] primvars:displayColor = [(0, 0, 1)]
        double radius = 2
    }
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;I&amp;rsquo;d say this is a fairly ill-advised approach to working with USD files, but it worked! No installs required.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;multiball_20230627T132245.usd&#34;&gt;example output layers&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;sphere_base.usd&#34;&gt;example sphere_base&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;sharing-the-work&#34;&gt;Sharing the work.&lt;/h2&gt;
&lt;p&gt;There is currently no good online viewer for USD geometries. I consider that a pretty significant weakness.&lt;/p&gt;
&lt;p&gt;I did experiment with importing into &lt;a href=&#34;https://docs.blender.org/manual/en/latest/files/import_export/usd.html&#34;&gt;Blender&lt;/a&gt; and then exporting to &lt;a href=&#34;https://www.web3d.org/getting-started-x3d&#34;&gt;&lt;code&gt;.x3d&lt;/code&gt;&lt;/a&gt;, however the mesh color data does not arrive into Blender with the current importer? It was a tick box&amp;hellip; did I miss it? I was pretty excited that the model came though! The color isn&amp;rsquo;t a material in this case. Perhaps if it was it would? As a note for future work, the color information can be added into the &lt;code&gt;.x3d&lt;/code&gt; looking something like:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-XML&#34; data-lang=&#34;XML&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;&amp;lt;Appearance&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;&amp;lt;Material&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;diffuseColor=&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#39;1 0 0&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;/&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;&amp;lt;/Appearance&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;There is an opportunity to create a what is referred to as a &lt;code&gt;rendering delegate&lt;/code&gt; here, and some people &lt;a href=&#34;https://github.com/autodesk-forks/USD/tree/hdJavaScript&#34;&gt;have started that work&lt;/a&gt;, but it seems to have stalled.&lt;/p&gt;
&lt;p&gt;Here is the x3d as I&amp;rsquo;ve played around with it a bit. &lt;a href=&#34;webview_with_color.x3d&#34;&gt;see raw&lt;/a&gt;&lt;/p&gt;
&lt;script type=&#39;text/javascript&#39; src=&#39;https://www.x3dom.org/download/x3dom.js&#39;&gt; &lt;/script&gt; 
&lt;x3d width=&#39;500px&#39; height=&#39;400px&#39;&gt; 
&lt;scene&gt;
&lt;inline url=&#34;webview_with_color.x3d&#34;&gt; &lt;/inline&gt; 
&lt;/scene&gt; 
&lt;/x3d&gt;  
&lt;p&gt;Next&amp;hellip; adding a Material!&lt;/p&gt;
</description>
    </item>
    
    
    
    <item>
      <title>What. I&#39;m taking my Spring Vacation in Hyrule.</title>
      <link>https://whynotestflight.com/excuses/what.-im-taking-my-spring-vacation-in-hyrule./</link>
      <pubDate>Sat, 20 May 2023 00:00:00 +0000</pubDate>
      
      <guid>https://whynotestflight.com/excuses/what.-im-taking-my-spring-vacation-in-hyrule./</guid>
      <description>&lt;p&gt;Tears of the Kingdom is very fun.&lt;/p&gt;
</description>
    </item>
    
    
    
    <item>
      <title>Mac -&gt; Linux: Everything you can do... I can do somewhat</title>
      <link>https://whynotestflight.com/excuses/mac-linux-everything-you-can-do...-i-can-do-somewhat/</link>
      <pubDate>Sat, 13 May 2023 00:00:00 +0000</pubDate>
      
      <guid>https://whynotestflight.com/excuses/mac-linux-everything-you-can-do...-i-can-do-somewhat/</guid>
      <description>&lt;p&gt;Got the &lt;a href=&#34;https://github.com/carlynorama/tipsy-robot-swift/releases/tag/helloLinux&#34;&gt;tipsy-robot-swift dev branch&lt;/a&gt; to run on Linux with some changes to &lt;a href=&#34;https://github.com/carlynorama/APItizer/releases/tag/helloLinux&#34;&gt;APITizer&lt;/a&gt; and &lt;a href=&#34;https://github.com/carlynorama/TrunkLine/releases/tag/helloLinux&#34;&gt;TrunkLink&lt;/a&gt; dev branches as well, much of the progress is on the APIng &lt;a href=&#34;https://github.com/carlynorama/APIng/tree/for_linux_test&#34;&gt;&amp;ldquo;for_linux_test&amp;rdquo;&lt;/a&gt; branch.&lt;/p&gt;
&lt;p&gt;All of this will need to be revisited after the release of the new Swift Foundation, presumably after WWDC 2023 in June. Many of these patches will probably be deleted.&lt;/p&gt;
&lt;h2 id=&#34;still-todo&#34;&gt;Still TODO&lt;/h2&gt;
&lt;p&gt;ServerSideEvents engine not implemented on Linux b/c currently uses the &lt;code&gt;URLSession.bytes(for)&lt;/code&gt; async convenience function and I don&amp;rsquo;t need it for phase 1 of my posts-only bot, and I&amp;rsquo;m just going to wait until after WWDC. References to it wrapped in &lt;code&gt;#if !os(Linux)&lt;/code&gt; checks.&lt;/p&gt;
&lt;h2 id=&#34;misc-headers&#34;&gt;Misc Headers&lt;/h2&gt;
&lt;p&gt;File headers where necessary.&lt;/p&gt;
&lt;h3 id=&#34;networking&#34;&gt;Networking&lt;/h3&gt;
&lt;p&gt;Used by Linux to load URLRequest, etc.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-Swift&#34; data-lang=&#34;Swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#if&lt;/span&gt; &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;canImport&lt;/span&gt;(&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;FoundationNetworking&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;FoundationNetworking&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#endif&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;uttypes&#34;&gt;UTTypes&lt;/h3&gt;
&lt;p&gt;Used by AppleOS b/c they have it.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-Swift&#34; data-lang=&#34;Swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#if&lt;/span&gt; &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;canImport&lt;/span&gt;(&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;UniformTypeIdentifiers&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;UniformTypeIdentifiers&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#endif&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Linux version has a kludge file to handle JUST what I use types for wrapped in &lt;code&gt;#if !canImport(UniformTypeIdentifiers)&lt;/code&gt;&lt;/p&gt;
&lt;h2 id=&#34;extensions&#34;&gt;Extensions&lt;/h2&gt;
&lt;h3 id=&#34;date&#34;&gt;Date&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;Date&lt;/code&gt;: only &lt;code&gt;func ISO8601Format() -&amp;gt; String&lt;/code&gt;, not needed for &lt;code&gt;APITizer&lt;/code&gt;, used in &lt;code&gt;TrunkLine&lt;/code&gt;&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#if&lt;/span&gt; &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;os&lt;/span&gt;(&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;Linux&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;Foundation&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;extension&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;Date&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;ISO8601Format&lt;/span&gt;() -&amp;gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;       &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;formatter&lt;/span&gt; = ISO8601DateFormatter()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;       &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; formatter.string(from: &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#endif&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;fileio&#34;&gt;FileIO&lt;/h3&gt;
&lt;p&gt;Updated helper &lt;code&gt;struct&lt;/code&gt; to deal with &lt;code&gt;URL&lt;/code&gt; problems.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;-  `initializer URL(filePath: filePath)` is still `URL(fileURLWithPath: filePath)`
- `.appending(component: folderName)` doesn&#39;t exist
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I broke the pattern with this and did if statements instead of implementing the extension. If still a thing post WWDC, will refactor.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;makeFileURL&lt;/span&gt;(filePath:&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;) -&amp;gt; URL {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;TODO:&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt; For iOS??&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//let locationToWrite = URL.documentsDirectory.appendingPathComponent(&amp;#34;testImage&amp;#34;, conformingTo: .png)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#if&lt;/span&gt; &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;os&lt;/span&gt;(&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;Linux&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; URL(fileURLWithPath: filePath)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#else&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#available&lt;/span&gt;(&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;macOS&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;13.0&lt;/span&gt;, &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;*&lt;/span&gt;) { &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//don&amp;#39;t know how to use this with linux check?&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;URL&lt;/span&gt;(&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;filePath&lt;/span&gt;: &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;filePath&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        } &lt;span style=&#34;color:#c6a0f6&#34;&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// Fallback on earlier versions&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;             &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; URL(fileURLWithPath: filePath)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#endif&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;urlsession&#34;&gt;URLSession&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;URLSession&lt;/code&gt;: add async convenience inits, with the exclusion of bytes (TODO if not added after WWDC)&lt;/p&gt;
&lt;p&gt;Example:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-Swift&#34; data-lang=&#34;Swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;extension&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;URLSession&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;upload&lt;/span&gt;(&lt;span style=&#34;color:#c6a0f6&#34;&gt;for&lt;/span&gt; request: URLRequest, from bodyData:Data, delegate: (URLSessionTaskDelegate)? = &lt;span style=&#34;color:#f5a97f&#34;&gt;nil&lt;/span&gt;) async &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; -&amp;gt; (Data, URLResponse) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;dataTask&lt;/span&gt;: URLSessionDataTask?
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;onCancel&lt;/span&gt; = { dataTask?.cancel() }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;rlocal&lt;/span&gt; = request
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        rlocal.httpMethod = &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;POST&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        rlocal.httpBody = bodyData
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; await withTaskCancellationHandler(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            operation: {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; await withCheckedThrowingContinuation { continuation &lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    dataTask = &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;.dataTask(with: rlocal) { data, response, error &lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                        &lt;span style=&#34;color:#c6a0f6&#34;&gt;guard&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;data&lt;/span&gt; = data, &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;response&lt;/span&gt; = response &lt;span style=&#34;color:#c6a0f6&#34;&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                            &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;error&lt;/span&gt; = error ?? URLError(.badServerResponse)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                            &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; continuation.resume(throwing: error)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                        continuation.resume(returning: (data, response))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    dataTask?.resume()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            },
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            onCancel: {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                onCancel()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        )
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;glue-implementations&#34;&gt;Glue Implementations&lt;/h2&gt;
&lt;h3 id=&#34;uttype&#34;&gt;UTType&lt;/h3&gt;
&lt;p&gt;UTType library doesn&amp;rsquo;t not exist on Linux. Wrote BARE-MINIUM hard coded make it work for image file detection. It is a mess and not worth sharing here, but you can go see it &lt;a href=&#34;https://github.com/carlynorama/APIng/blob/for_linux_test/Sources/APIng/Linux%2BUTType.swift&#34;&gt;https://github.com/carlynorama/APIng/blob/for_linux_test/Sources/APIng/Linux%2BUTType.swift&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&#34;actually-thats-an-improvement&#34;&gt;Actually&amp;hellip; that&amp;rsquo;s an Improvement&lt;/h2&gt;
&lt;p&gt;In &lt;a href=&#34;https://github.com/carlynorama/APIng/blob/for_linux_test/Sources/APIng/POSTEncoders.swift&#34;&gt;&lt;code&gt;POSTEncoders&lt;/code&gt;&lt;/a&gt;) discovered new-to-me non-objectiveC way to detect Optional&lt;Any&gt; == nil for &lt;code&gt;func makeDictionary(from itemToEncode:Any) -&amp;gt; [String:String]?&lt;/code&gt;. Both ways are in &lt;a href=&#34;https://github.com/carlynorama/APIng/blob/for_linux_test/&#34;&gt;APIng&lt;/a&gt;, only the new way got moved to &lt;a href=&#34;https://github.com/carlynorama/APITizer/blob/dev&#34;&gt;&lt;code&gt;APITizer&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; child.value &lt;span style=&#34;color:#c6a0f6&#34;&gt;is&lt;/span&gt; ExpressibleByNilLiteral  {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;switch&lt;/span&gt; child.value {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;case&lt;/span&gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;Optional&lt;/span&gt;&amp;lt;&lt;span style=&#34;color:#91d7e3&#34;&gt;Any&lt;/span&gt;&amp;gt;.&lt;span style=&#34;color:#c6a0f6&#34;&gt;none&lt;/span&gt;: &lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Nil!&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;default&lt;/span&gt;: 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Not nil!&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; (&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt;, some) = Mirror(reflecting: child.value).children.&lt;span style=&#34;color:#91d7e3&#34;&gt;first&lt;/span&gt;!
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//print(some)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            dictionary[key] = &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;(describing: some)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//     //OLD: &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//     //https://forums.swift.org/t/calling-object-getclass-on-swift-objects/62790/4&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//     let typeDescription = object_getClass(child.value)?.description() ?? &amp;#34;&amp;#34; //Not in linux.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//     if !typeDescription.contains(&amp;#34;Null&amp;#34;) &amp;amp;&amp;amp; !typeDescription.contains(&amp;#34;Empty&amp;#34;) {&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//         let (_, some) = Mirror(reflecting: child.value).children.first!&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//         //print(some)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//         dictionary[key] = String(describing: some)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//     }&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;} &lt;span style=&#34;color:#c6a0f6&#34;&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    dictionary[key] = &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;(describing: child.value)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description>
    </item>
    
    
    
    <item>
      <title>Now I need Linux to test on.</title>
      <link>https://whynotestflight.com/excuses/now-i-need-linux-to-test-on./</link>
      <pubDate>Sat, 22 Apr 2023 00:00:00 +0000</pubDate>
      
      <guid>https://whynotestflight.com/excuses/now-i-need-linux-to-test-on./</guid>
      <description>&lt;p&gt;Eventually I want to run Tipsy-Robot with the png generator on little micro-computer here in the house. Getting from developing on my Mac to that little nugget means cross checking everything on Linux.&lt;/p&gt;
&lt;p&gt;Two examples on how to verify things work: a VM and a GitHub Action&lt;/p&gt;
&lt;h2 id=&#34;semi-virtual-virtualbox&#34;&gt;Semi-Virtual VirtualBox&lt;/h2&gt;
&lt;p&gt;I use VirtualBox as my VM. Conveniences like being able to copy paste between windows makes working on a code base for both environments super easy.&lt;/p&gt;
&lt;h3 id=&#34;misc-brief-notes-on-setting-up-virtualbox&#34;&gt;Misc brief notes on setting up VirtualBox&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;Go get Virtual Box: &lt;a href=&#34;https://www.virtualbox.org/wiki/Downloads&#34;&gt;https://www.virtualbox.org/wiki/Downloads&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Install&lt;/li&gt;
&lt;li&gt;Go get ISO, ubuntu, LTS stands for Long Term Support&lt;/li&gt;
&lt;li&gt;New&lt;/li&gt;
&lt;li&gt;Setup Permission for VirtualBox “Input Monitoring”&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Misc Other&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Set the scree size&lt;/li&gt;
&lt;li&gt;Add terminal to favorites&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://www.virtualbox.org/manual/ch04.html&#34;&gt;https://www.virtualbox.org/manual/ch04.html&lt;/a&gt;. // install guest device got to Devices&amp;gt; to turn them on&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://www.howtogeek.com/307701/how-to-customize-and-colorize-your-bash-prompt/&#34;&gt;https://www.howtogeek.com/307701/how-to-customize-and-colorize-your-bash-prompt/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://wiki.archlinux.org/title/Bash/Prompt_customization&#34;&gt;https://wiki.archlinux.org/title/Bash/Prompt_customization&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;add-swift-the-long-way&#34;&gt;Add Swift The Long Way&lt;/h3&gt;
&lt;p&gt;&lt;a href=&#34;https://www.swift.org/server/guides/deploying/ubuntu.html&#34;&gt;Official Instructions&lt;/a&gt;&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-zsh&#34; data-lang=&#34;zsh&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;sudo apt update
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;sudo apt upgrade
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;sudo apt install clang libicu-dev build-essential pkg-config
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;mkdir ~/swift
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#91d7e3&#34;&gt;cd&lt;/span&gt; ~/swift
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# go to https://www.swift.org/download/#releases for current links&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;wget https://download.swift.org/swift-5.8-release/ubuntu2004/swift-5.8-RELEASE/swift-5.8-RELEASE-ubuntu20.04.tar.gz
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;tar xzf swift-5.8-RELEASE-ubuntu20.04.tar.gz &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#add v (xzvf) to see all files&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;mv swift-5.8-RELEASE-ubuntu22.04 5.8
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# swift.org recommended choice: add a simlink to `swift` command to `/usr/bin/` &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# instead of adding version folder to $PATH. &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;sudo ln -s ~/swift/5.8/usr/bin/swift /usr/bin/swift 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;swift --version
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Add what we need:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-zsh&#34; data-lang=&#34;zsh&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;sudo apt install git 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;sudo apt install gh  &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#optional&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;sudo apt install libpng-dev
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;mkdir ~/Documents/GitHub
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#91d7e3&#34;&gt;cd&lt;/span&gt; ~/Documents/GitHub
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;gh auth login &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#https://cli.github.com/manual/gh_auth_login&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;gh repo clone carlynorama/SwiftLIBPNG
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#or&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;git@github.com:carlynorama/SwiftLIBPNG.git
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#91d7e3&#34;&gt;cd&lt;/span&gt; SwiftLIBPNG
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;swift build
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;If installing VScode will also need sourcekit-lsp. Discussion: &lt;a href=&#34;https://forums.swift.org/t/vscode-extension/29722&#34;&gt;https://forums.swift.org/t/vscode-extension/29722&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&#34;super-virtual-linux-github-action&#34;&gt;Super Virtual Linux (Github Action)&lt;/h2&gt;
&lt;p&gt;Use action like one checking &lt;a href=&#34;https://github.com/carlynorama/APItizer/actions&#34;&gt;APITizer&lt;/a&gt;&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-yml&#34; data-lang=&#34;yml&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;name&lt;/span&gt;: Build Linux
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;on&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#c6a0f6&#34;&gt;push&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;branches&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      - &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#39;*&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#c6a0f6&#34;&gt;pull_request&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;branches&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      - main
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;jobs&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#c6a0f6&#34;&gt;build&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;name&lt;/span&gt;: Build Linux
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;runs-on&lt;/span&gt;: ubuntu-latest
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;container&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#c6a0f6&#34;&gt;image&lt;/span&gt;: swift:latest
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;steps&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      - &lt;span style=&#34;color:#c6a0f6&#34;&gt;name&lt;/span&gt;: Checkout
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;uses&lt;/span&gt;: actions/checkout@v3
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      - &lt;span style=&#34;color:#c6a0f6&#34;&gt;name&lt;/span&gt;: Install sudo package
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;run&lt;/span&gt;: apt update &amp;amp;&amp;amp; apt install sudo
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      - &lt;span style=&#34;color:#c6a0f6&#34;&gt;name&lt;/span&gt;: Install libpng
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;run&lt;/span&gt;: |&lt;span style=&#34;color:#6e738d&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d&#34;&gt;          sudo apt-get install libpng-dev -y&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      - &lt;span style=&#34;color:#c6a0f6&#34;&gt;name&lt;/span&gt;: Build and Test
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;run&lt;/span&gt;: |&lt;span style=&#34;color:#6e738d&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d&#34;&gt;           swift build
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d&#34;&gt;           swift test&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;TODO: Cache the image with libpng?&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://stackoverflow.com/questions/57982945/how-to-apt-get-install-in-a-github-actions-workflow&#34;&gt;https://stackoverflow.com/questions/57982945/how-to-apt-get-install-in-a-github-actions-workflow&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://stackoverflow.com/questions/59269850/caching-apt-packages-in-github-actions-workflow/73500415#73500415&#34;&gt;https://stackoverflow.com/questions/59269850/caching-apt-packages-in-github-actions-workflow/73500415#73500415&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</description>
    </item>
    
    
    
    <item>
      <title>Can libpng give me something other than a hard exit?</title>
      <link>https://whynotestflight.com/excuses/can-libpng-give-me-something-other-than-a-hard-exit/</link>
      <pubDate>Tue, 18 Apr 2023 00:00:00 +0000</pubDate>
      
      <guid>https://whynotestflight.com/excuses/can-libpng-give-me-something-other-than-a-hard-exit/</guid>
      <description>&lt;p&gt;&lt;a href=&#34;https://whynotestflight.com/excuses/pngs-are-cool/&#34;&gt;Last week&lt;/a&gt; I mentioned that &lt;code&gt;libpng&lt;/code&gt; uses &amp;ldquo;long jumps&amp;rdquo;, i.e. &lt;code&gt;setjmp&lt;/code&gt; to bop around exiting code that doesn&amp;rsquo;t do what it is supposed to do. That can be tricky to manage, but it is C. It&amp;rsquo;s all tricky to manage.&lt;/p&gt;
&lt;p&gt;I tried to make an example that would exit into Swift, but I couldn&amp;rsquo;t get the Swift to anything other than hard exit (search last week&amp;rsquo;s post for &lt;code&gt;writeErrorCallback&lt;/code&gt;). There does not appear to be a way to gracefully leave &lt;code&gt;libpng&lt;/code&gt; through that door.&lt;/p&gt;
&lt;p&gt;The solution, more C code.&lt;/p&gt;
&lt;p&gt;The basic model of what I&amp;rsquo;ve done is to write a C function that wraps the calls to &lt;code&gt;libpng&lt;/code&gt; and sets the long jump definitions accordingly. This allows for a developers-choice int to be returned if something goes wrong.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-C&#34; data-lang=&#34;C&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;int&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;pngb_set_IHDR&lt;/span&gt;(png_structp png_ptr, png_infop info_ptr, png_uint_32 width, png_uint_32 height, &lt;span style=&#34;color:#ed8796&#34;&gt;int&lt;/span&gt; bit_depth, &lt;span style=&#34;color:#ed8796&#34;&gt;int&lt;/span&gt; color_type, &lt;span style=&#34;color:#ed8796&#34;&gt;int&lt;/span&gt; interlace_method, &lt;span style=&#34;color:#ed8796&#34;&gt;int&lt;/span&gt; compression_method, &lt;span style=&#34;color:#ed8796&#34;&gt;int&lt;/span&gt; filter_method) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; (&lt;span style=&#34;color:#8aadf4&#34;&gt;setjmp&lt;/span&gt;(&lt;span style=&#34;color:#8aadf4&#34;&gt;png_jmpbuf&lt;/span&gt;(png_ptr))) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#8aadf4&#34;&gt;png_destroy_write_struct&lt;/span&gt;(&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;amp;&lt;/span&gt;png_ptr, &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;amp;&lt;/span&gt;info_ptr);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;2&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#8aadf4&#34;&gt;png_set_IHDR&lt;/span&gt;(png_ptr, info_ptr, width, height, bit_depth, color_type, interlace_method, compression_method, filter_method);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;0&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;There is then a companion Swift function that throws the appropriate error:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-Swift&#34; data-lang=&#34;Swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;setIHDR&lt;/span&gt;(png_ptr:OpaquePointer, info_ptr:OpaquePointer, width:&lt;span style=&#34;color:#91d7e3&#34;&gt;UInt32&lt;/span&gt;, height:&lt;span style=&#34;color:#91d7e3&#34;&gt;UInt32&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                        bitDepth:&lt;span style=&#34;color:#91d7e3&#34;&gt;Int32&lt;/span&gt;, colorType:&lt;span style=&#34;color:#91d7e3&#34;&gt;Int32&lt;/span&gt;) &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;result&lt;/span&gt; = pngb_set_IHDR(png_ptr, info_ptr, width, height, bitDepth, colorType,                     
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                                   PNG_INTERLACE_NONE,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                                   PNG_COMPRESSION_TYPE_DEFAULT,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                                   PNG_FILTER_TYPE_DEFAULT)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; result &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;!=&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;0&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//PNGError implemented with an init that takes a code.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;throw&lt;/span&gt; PNGError(result) 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;It means:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Lots of boiler plate for almost every libpng function call (just the ones that can fail)&lt;/li&gt;
&lt;li&gt;A performance slow down for all the extra code checking.&lt;/li&gt;
&lt;li&gt;A whole separate target written in C.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If there is a frequently bundled together set of tasks for libpng to do, it would be better to write the implementation in C, and then have the one Swift wrapper for that one bigger function, if speed is of the essence.&lt;/p&gt;
&lt;h2 id=&#34;c-wrapper-for-libpng&#34;&gt;C Wrapper for libpng&lt;/h2&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-C&#34; data-lang=&#34;C&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//  png_for_swift.c
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//  
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//  Created by Carlyn Maw on 4/13/23.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#include&lt;/span&gt; &lt;span style=&#34;color:#6e738d;font-weight:bold;font-style:italic&#34;&gt;&amp;lt;stdlib.h&amp;gt;&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#include&lt;/span&gt; &lt;span style=&#34;color:#6e738d;font-weight:bold;font-style:italic&#34;&gt;&amp;lt;png.h&amp;gt;&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#include&lt;/span&gt; &lt;span style=&#34;color:#6e738d;font-weight:bold;font-style:italic&#34;&gt;&amp;#34;png_for_swift.h&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//TOO GLITCHY do not use. 
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//int pngb_set_default_data_write_exit(png_structpp png_ptrp, png_infopp info_ptrp) {
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//    if (setjmp(png_jmpbuf(*png_ptrp))) {
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//        printf(&amp;#34;png_for_swift: I&amp;#39;m outta here, %p, %p, %p, %p\n&amp;#34;, png_ptrp, info_ptrp, *png_ptrp, *info_ptrp);
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//        //Have to destroy back in Swift code b/c something hinky with the pointer (especially info).
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//        //png_destroy_write_struct(png_ptrp, info_ptrp);
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//        return 2;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//    }
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//}
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;int&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;pngb_set_IHDR&lt;/span&gt;(png_structp png_ptr, png_infop info_ptr, png_uint_32 width, png_uint_32 height, &lt;span style=&#34;color:#ed8796&#34;&gt;int&lt;/span&gt; bit_depth, &lt;span style=&#34;color:#ed8796&#34;&gt;int&lt;/span&gt; color_type, &lt;span style=&#34;color:#ed8796&#34;&gt;int&lt;/span&gt; interlace_method, &lt;span style=&#34;color:#ed8796&#34;&gt;int&lt;/span&gt; compression_method, &lt;span style=&#34;color:#ed8796&#34;&gt;int&lt;/span&gt; filter_method) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; (&lt;span style=&#34;color:#8aadf4&#34;&gt;setjmp&lt;/span&gt;(&lt;span style=&#34;color:#8aadf4&#34;&gt;png_jmpbuf&lt;/span&gt;(png_ptr))) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#8aadf4&#34;&gt;png_destroy_write_struct&lt;/span&gt;(&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;amp;&lt;/span&gt;png_ptr, &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;amp;&lt;/span&gt;info_ptr);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;2&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#8aadf4&#34;&gt;png_set_IHDR&lt;/span&gt;(png_ptr, info_ptr, width, height, bit_depth, color_type, interlace_method, compression_method, filter_method);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;0&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;int&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;pngb_set_rows&lt;/span&gt;(png_structp png_ptr, png_infop info_ptr, png_bytepp row_pointers) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; (&lt;span style=&#34;color:#8aadf4&#34;&gt;setjmp&lt;/span&gt;(&lt;span style=&#34;color:#8aadf4&#34;&gt;png_jmpbuf&lt;/span&gt;(png_ptr))) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#8aadf4&#34;&gt;printf&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;set rows error&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#8aadf4&#34;&gt;png_destroy_write_struct&lt;/span&gt;(&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;amp;&lt;/span&gt;png_ptr, &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;amp;&lt;/span&gt;info_ptr);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;3&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#8aadf4&#34;&gt;png_set_rows&lt;/span&gt;(png_ptr, info_ptr, row_pointers);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;0&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;int&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;pngb_write_png&lt;/span&gt;(png_structp png_ptr, png_infop info_ptr, &lt;span style=&#34;color:#ed8796&#34;&gt;int&lt;/span&gt; transforms, png_voidp params) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; (&lt;span style=&#34;color:#8aadf4&#34;&gt;setjmp&lt;/span&gt;(&lt;span style=&#34;color:#8aadf4&#34;&gt;png_jmpbuf&lt;/span&gt;(png_ptr))) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#8aadf4&#34;&gt;printf&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;write_png error&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#8aadf4&#34;&gt;png_destroy_write_struct&lt;/span&gt;(&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;amp;&lt;/span&gt;png_ptr, &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;amp;&lt;/span&gt;info_ptr);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;4&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#8aadf4&#34;&gt;png_write_png&lt;/span&gt;(png_ptr, info_ptr, transforms, params);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//TODO: calls png_warning but never png_error
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//https://github.com/glennrp/libpng/pngwio.c
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;int&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;pngb_set_write_fn&lt;/span&gt;(png_structrp png_ptr, png_voidp io_ptr, png_rw_ptr write_data_fn, png_flush_ptr output_flush_fn) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; (&lt;span style=&#34;color:#8aadf4&#34;&gt;setjmp&lt;/span&gt;(&lt;span style=&#34;color:#8aadf4&#34;&gt;png_jmpbuf&lt;/span&gt;(png_ptr))) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#8aadf4&#34;&gt;printf&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;write_png error&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;5&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#8aadf4&#34;&gt;png_set_write_fn&lt;/span&gt;(png_ptr, io_ptr, write_data_fn, output_flush_fn);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;0&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//png_set_write_status_fn does not call png_warning or png_error
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//int pngb_set_write_status_fn(png_structrp png_ptr, png_write_status_ptr write_row_fn) {
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//    if (setjmp(png_jmpbuf(png_ptr))) {
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//        printf(&amp;#34;write_png error&amp;#34;);
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//        return 5;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//    }
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//    png_set_write_status_fn(png_ptr, write_row_fn);
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//    return 0;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//}
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;the-swift-that-wraps-the-c&#34;&gt;The Swift that Wraps the C&lt;/h2&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-Swift&#34; data-lang=&#34;Swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//  SwiftLIBPNG+ThrowingData.swift&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//  Created by Carlyn Maw on 4/15/23.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#if&lt;/span&gt; &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;os&lt;/span&gt;(&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;Linux&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;Glibc&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#else&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;Darwin&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#endif&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;Foundation&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;png&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;CBridgePNG&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;extension&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;SwiftLIBPNG&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;pngData&lt;/span&gt;(&lt;span style=&#34;color:#c6a0f6&#34;&gt;for&lt;/span&gt; pixelData:[&lt;span style=&#34;color:#91d7e3&#34;&gt;UInt8&lt;/span&gt;], width:&lt;span style=&#34;color:#91d7e3&#34;&gt;UInt32&lt;/span&gt;, height:&lt;span style=&#34;color:#91d7e3&#34;&gt;UInt32&lt;/span&gt;) &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; -&amp;gt; Data {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;pixelsCopy&lt;/span&gt; = pixelData &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;TODO:&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt; This or inout? OR... is there away around need for MutableCopy?&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;bitDepth&lt;/span&gt;:&lt;span style=&#34;color:#91d7e3&#34;&gt;UInt8&lt;/span&gt; = &lt;span style=&#34;color:#f5a97f&#34;&gt;8&lt;/span&gt; &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//(1 byte, values 1, 2, 4, 8, or 16) (has to be 8 or 16 for RGBA)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;colorType&lt;/span&gt; = PNG_COLOR_TYPE_RGBA &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//UInt8(6), (1 byte, values 0, 2, 3, 4, or 6) (6 == red, green, blue and alpha)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;pngIOBuffer&lt;/span&gt; = Data()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#91d7e3&#34;&gt;withUnsafePointer&lt;/span&gt;(to: pngIOBuffer) { &lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;io buffer declared: &lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;$0&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;) }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;png_ptr&lt;/span&gt;:OpaquePointer? = png_create_write_struct(PNG_LIBPNG_VER_STRING, &lt;span style=&#34;color:#f5a97f&#34;&gt;nil&lt;/span&gt;, &lt;span style=&#34;color:#f5a97f&#34;&gt;nil&lt;/span&gt;, &lt;span style=&#34;color:#f5a97f&#34;&gt;nil&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; (png_ptr == &lt;span style=&#34;color:#f5a97f&#34;&gt;nil&lt;/span&gt;) { &lt;span style=&#34;color:#c6a0f6&#34;&gt;throw&lt;/span&gt; PNGError.outOfMemory }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;info_ptr&lt;/span&gt;:OpaquePointer? = png_create_info_struct(png_ptr);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; (info_ptr == &lt;span style=&#34;color:#f5a97f&#34;&gt;nil&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            png_destroy_write_struct(&amp;amp;png_ptr, &lt;span style=&#34;color:#f5a97f&#34;&gt;nil&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;throw&lt;/span&gt; PNGError.outOfMemory;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;TODO:&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt; Will setWriteBehavior ever throw?&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//underlying libpng function calls png_warning, but not png_error.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;do&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; setWriteBehavior(png_ptr: png_ptr, bufferPointer: &amp;amp;pngIOBuffer, write_callback: writeDataCallback, flush_callback: &lt;span style=&#34;color:#f5a97f&#34;&gt;nil&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        } &lt;span style=&#34;color:#c6a0f6&#34;&gt;catch&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            png_destroy_write_struct(&amp;amp;png_ptr, &amp;amp;info_ptr);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;throw&lt;/span&gt; PNGError.message(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Couldn&amp;#39;t set callbacks&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//Can call libpng function directly because it cannot fail i.e.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//no png_warning(), no png_error() in actual function.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//Can give it a bad value as a call back pointer, but it will take it without verification.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        png_set_write_status_fn(png_ptr) { png_ptr, row, pass &lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(png_ptr ?? &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;nil&amp;#34;&lt;/span&gt;, row, pass)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//---------------------------------------------------------------- IHDR&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; setIHDR(png_ptr: png_ptr!, info_ptr: info_ptr!, width: width, height: height, bitDepth: &lt;span style=&#34;color:#91d7e3&#34;&gt;Int32&lt;/span&gt;(bitDepth), colorType: colorType)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//Note, if instead we were doing the &amp;#34;long form&amp;#34; save we could change the compression&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//schemes mid image. (And this is why you use ImageMagick...)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; pixelsCopy.withUnsafeMutableBufferPointer{ pd_pointer &lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;row_pointers&lt;/span&gt;:[&lt;span style=&#34;color:#91d7e3&#34;&gt;Optional&lt;/span&gt;&amp;lt;&lt;span style=&#34;color:#91d7e3&#34;&gt;UnsafeMutablePointer&lt;/span&gt;&amp;lt;&lt;span style=&#34;color:#91d7e3&#34;&gt;UInt8&lt;/span&gt;&amp;gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;gt;&lt;/span&gt;] = []
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;for&lt;/span&gt; rowIndex &lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;0.&lt;/span&gt;.&amp;lt;height {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;rowStart&lt;/span&gt; = rowIndex &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;*&lt;/span&gt; width &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;*&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;4&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                row_pointers.append(pd_pointer.baseAddress! &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;+&lt;/span&gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;Int&lt;/span&gt;(rowStart))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; setRows(png_ptr: png_ptr, info_ptr: info_ptr, rowPointers: &amp;amp;row_pointers)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; pushPNGData(png_ptr: png_ptr, info_ptr: info_ptr, transforms: PNG_TRANSFORM_IDENTITY, params: &lt;span style=&#34;color:#f5a97f&#34;&gt;nil&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//--------------------------------------------------------   PNG CLEANUP&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        png_destroy_write_struct(&amp;amp;png_ptr, &amp;amp;info_ptr);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//---------------------------------------------------------------------&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; pngIOBuffer
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;setIHDR&lt;/span&gt;(png_ptr:OpaquePointer, info_ptr:OpaquePointer, width:&lt;span style=&#34;color:#91d7e3&#34;&gt;UInt32&lt;/span&gt;, height:&lt;span style=&#34;color:#91d7e3&#34;&gt;UInt32&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                        bitDepth:&lt;span style=&#34;color:#91d7e3&#34;&gt;Int32&lt;/span&gt;, colorType:&lt;span style=&#34;color:#91d7e3&#34;&gt;Int32&lt;/span&gt;) &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;result&lt;/span&gt; = pngb_set_IHDR(png_ptr, info_ptr, width, height,  bitDepth, colorType,                      
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                                   PNG_INTERLACE_NONE,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                                   PNG_COMPRESSION_TYPE_DEFAULT,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                                   PNG_FILTER_TYPE_DEFAULT)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; result &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;!=&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;0&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;throw&lt;/span&gt; PNGError(result)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;setRows&lt;/span&gt;(png_ptr:OpaquePointer?, info_ptr:OpaquePointer?, rowPointers:png_bytepp?) &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;result&lt;/span&gt; = pngb_set_rows(png_ptr, info_ptr, rowPointers)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; result &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;!=&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;0&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;throw&lt;/span&gt; PNGError(result)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;pushPNGData&lt;/span&gt;(png_ptr:OpaquePointer?, info_ptr:OpaquePointer?, transforms:&lt;span style=&#34;color:#91d7e3&#34;&gt;Int32&lt;/span&gt;, params:&lt;span style=&#34;color:#91d7e3&#34;&gt;Optional&lt;/span&gt;&amp;lt;UnsafeMutableRawPointer&amp;gt; = &lt;span style=&#34;color:#f5a97f&#34;&gt;nil&lt;/span&gt;) &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;result&lt;/span&gt; = pngb_write_png(png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, params)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; result &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;!=&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;0&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;throw&lt;/span&gt; PNGError(result)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//Needs Cleanup because underlying libpng function does not take in info_ptr and&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//info ptr is need for destroy.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;setWriteBehavior&lt;/span&gt;(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        png_ptr:OpaquePointer?,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        bufferPointer:&lt;span style=&#34;color:#91d7e3&#34;&gt;Optional&lt;/span&gt;&amp;lt;UnsafeMutableRawPointer&amp;gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        write_callback:@convention(c) (&lt;span style=&#34;color:#91d7e3&#34;&gt;Optional&lt;/span&gt;&amp;lt;OpaquePointer&amp;gt;, &lt;span style=&#34;color:#91d7e3&#34;&gt;Optional&lt;/span&gt;&amp;lt;&lt;span style=&#34;color:#91d7e3&#34;&gt;UnsafeMutablePointer&lt;/span&gt;&amp;lt;&lt;span style=&#34;color:#91d7e3&#34;&gt;UInt8&lt;/span&gt;&amp;gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;gt;&lt;/span&gt;, &lt;span style=&#34;color:#91d7e3&#34;&gt;Int&lt;/span&gt;) -&amp;gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;Void&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        flush_callback:&lt;span style=&#34;color:#91d7e3&#34;&gt;Optional&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;lt;&lt;/span&gt;@convention(c) (&lt;span style=&#34;color:#91d7e3&#34;&gt;Optional&lt;/span&gt;&amp;lt;OpaquePointer&amp;gt;) -&amp;gt; ()&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    ) &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;result&lt;/span&gt; = pngb_set_write_fn(png_ptr, bufferPointer, write_callback, flush_callback)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; result &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;!=&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;0&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;throw&lt;/span&gt; PNGError(result)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//Needs Cleanup&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//Uncessary because underlying libpng function does not jump.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//    static func setWriteStatusUpdateBehavior(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//        png_ptr:OpaquePointer?,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//        status_callback:@convention(c) (Optional&amp;lt;OpaquePointer&amp;gt;, UInt32, Int32) -&amp;gt; ()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//    ) throws {&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//        let result = pngb_set_write_status_fn(png_ptr, status_callback)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//        if result != 0 {&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//            throw PNGError(result)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//        }&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//    }&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description>
    </item>
    
    
    
    <item>
      <title>png&#39;s are COOL</title>
      <link>https://whynotestflight.com/excuses/pngs-are-cool/</link>
      <pubDate>Tue, 11 Apr 2023 00:00:00 +0000</pubDate>
      
      <guid>https://whynotestflight.com/excuses/pngs-are-cool/</guid>
      <description>&lt;p&gt;So made a lot of progress on that libpng wrapper: &lt;a href=&#34;https://github.com/carlynorama/SwiftLIBPNG&#34;&gt;https://github.com/carlynorama/SwiftLIBPNG&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;So far, it compiles fine for MacOS 13+ (Swift 5.7, Xcode 14) using both Intel and M1 hardware with &lt;code&gt;libpng&lt;/code&gt; installed via homebrew.&lt;/p&gt;
&lt;h2 id=&#34;alternatives-of-note&#34;&gt;Alternatives of Note&lt;/h2&gt;
&lt;p&gt;If using a libpng library to avoid Apple-Hardware dependencies, also consider a Package that is all Swift, no C, no Foundation? As of 2023 APR these two had fairly recent activity.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/tayloraswift/swift-png&#34;&gt;https://github.com/tayloraswift/swift-png&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://swiftpackageindex.com/rbruinier/SwiftMicroPNG&#34;&gt;https://swiftpackageindex.com/rbruinier/SwiftMicroPNG&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;resources&#34;&gt;Resources&lt;/h2&gt;
&lt;h3 id=&#34;about-libpng&#34;&gt;About libpng&lt;/h3&gt;
&lt;p&gt;Although some people will tell you that PNG stands for Portable Network Graphic, that is not the original meaning. The recursive pun &amp;ldquo;PNG Not Gif&amp;rdquo; is how it started. The official documentation is riddled with the same humor and very deep knowledge about how computers, color and people work. Still worth a read. PNG&amp;rsquo;s are very cool.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;The main site: &lt;a href=&#34;http://www.libpng.org&#34;&gt;http://www.libpng.org&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;How PNGs work. Code is out of date but still very much a good read: &lt;a href=&#34;http://www.libpng.org/pub/png/book/&#34;&gt;http://www.libpng.org/pub/png/book/&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;More up to date than /book/ but still seems to lag :&lt;a href=&#34;http://www.libpng.org/pub/png/libpng-manual.txt&#34;&gt;http://www.libpng.org/pub/png/libpng-manual.txt&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Actual most recent: &lt;a href=&#34;https://github.com/glennrp/libpng/&#34;&gt;https://github.com/glennrp/libpng/&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&amp;lsquo;just the spec ma&amp;rsquo;am&amp;rsquo; - &lt;a href=&#34;https://www.w3.org/TR/2003/REC-PNG-20031110/&#34;&gt;https://www.w3.org/TR/2003/REC-PNG-20031110/&lt;/a&gt;, &lt;a href=&#34;https://w3c.github.io/PNG-spec/&#34;&gt;https://w3c.github.io/PNG-spec/&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;zlib spec for analyzing IDAT &lt;a href=&#34;https://www.zlib.net/manual.html&#34;&gt;https://www.zlib.net/manual.html&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;inspecting-data&#34;&gt;Inspecting Data&lt;/h3&gt;
&lt;p&gt;To just look at the HEX&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://hexed.it&#34;&gt;https://hexed.it&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;VSCode plugin Microsoft Hex Editor&lt;/li&gt;
&lt;li&gt;Shell option 1 &lt;code&gt;od -t x1 png-transparent.png&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Shell option 2 for bigger files &lt;code&gt;tail -f png-transparent.png | hexdump -C&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Testing and verification&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Very handy PNG verifier: &lt;a href=&#34;https://www.nayuki.io/page/png-file-chunk-inspector&#34;&gt;https://www.nayuki.io/page/png-file-chunk-inspector&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&amp;ldquo;The &amp;ldquo;official&amp;rdquo; test-suite for PNG&amp;rdquo; &lt;a href=&#34;http://www.schaik.com/pngsuite/&#34;&gt;http://www.schaik.com/pngsuite/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;notes&#34;&gt;Notes&lt;/h2&gt;
&lt;h3 id=&#34;managing-the-pointers&#34;&gt;Managing the pointers&lt;/h3&gt;
&lt;p&gt;To use &lt;code&gt;libpng&lt;/code&gt; to read or write the first step is to allocate memory for structs &lt;code&gt;libpng&lt;/code&gt; will use to store information about the png and its settings.&lt;/p&gt;
&lt;p&gt;From the documentation (on how to read, but a png_ptr and info_ptr are used for both reading a writing):&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The struct at which png_ptr points is used internally by libpng to keep track of the current state of the PNG image at any given moment; info_ptr is used to indicate what its state will be after all of the user-requested transformations are performed. One can also allocate a second information struct, usually referenced via an end_ptr variable; this can be used to hold all of the PNG chunk information that comes after the image data, in case it is important to keep pre- and post-IDAT information separate (as in an image editor, which should preserve as much of the existing PNG structure as possible). For this application, we don&amp;rsquo;t care where the chunk information comes from, so we will forego the end_ptr information struct and direct everything to info_ptr.&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;The functions &lt;code&gt;libpng&lt;/code&gt; provides for this come in two flavors, ones that return pointers and ones that take them and their handling functions in:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    png_structp png_ptr &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;png_create_write_struct&lt;/span&gt;(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        PNG_LIBPNG_VER_STRING,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        (png_voidp)user_error_ptr, 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        user_error_fn, 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        user_warning_fn
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    );
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    png_structp png_ptr &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;png_create_write_struct_2&lt;/span&gt;(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        PNG_LIBPNG_VER_STRING, 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            (png_voidp)user_error_ptr,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            user_error_fn, 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            user_warning_fn, 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            (png_voidp)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            user_mem_ptr, 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            user_malloc_fn, 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            user_free_fn
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    );
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Both styles of struct creation still require a call to &lt;code&gt;png_destroy_write_structs&lt;/code&gt; functions on wrap up. Memory management is a big deal in C. Always write the destroy with the create, like closing a parens.&lt;/p&gt;
&lt;h3 id=&#34;most-of-the-example-code-has-a-set_jmp-why-not-yours-yet&#34;&gt;Most of the example code has a set_jmp? Why not yours? (yet)&lt;/h3&gt;
&lt;p&gt;A lot of example code has a chunk along the lines of: &lt;code&gt;if (setjmp(png_jmpbuf(png_ptr))) { /* DO THIS */ }&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;This overrides the default error handling if the file received is not a PNG file, for example. The default behaviors seem to be print statements and PNG_ABORT, from what I can tell, so it would be good to override them. However, using setjmp() and longjmp() to do that is not guaranteed to be thread safe. There is some ambiguity in the documentation (to me), but it seems as if the compiler flag to allow the setting of jumpdef is on by default because the newish &amp;ldquo;Simplified API&amp;rdquo; needs it. (It appears it was off by default in 1.4, but now is on again). Some implementations on libpng turn it off.&lt;/p&gt;
&lt;p&gt;Why hassle with this very C specific type of error handling? The setjmp saves the calling environment to be used by longjmp. This means inside the setjmp block using png_ptr, info_ptr, or even returning will all work. C callbacks, by contrast, can only use what get offered to them as parameters.&lt;/p&gt;
&lt;p&gt;Look in example code for&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;PNG_SETJMP_NOT_SUPPORTED&lt;/code&gt; in older code&lt;/li&gt;
&lt;li&gt;&lt;code&gt;#define PNG_NO_SETJMP&lt;/code&gt; turns the feature off &lt;code&gt;#define PNG_SETJMP_SUPPORTED&lt;/code&gt; turns the feature on)&lt;/li&gt;
&lt;li&gt;Also might be &lt;code&gt;#undef PNG_SETJMP_SUPPORTED&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;#include &amp;lt;setjmp.h&amp;gt;&lt;/code&gt; is an indicator the code will be using &lt;code&gt;png_jmpbuf&lt;/code&gt; style error setting&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For more information on libpng and setjmp/longjmp:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;search for &amp;ldquo;Setjmp/longjmp issues&amp;rdquo; &lt;a href=&#34;https://github.com/glennrp/libpng/blob/12222e6fbdc90523be77633ed430144cfee22772/INSTALL&#34;&gt;INSTALL guide&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Also:&lt;a href=&#34;https://github.com/glennrp/libpng/blob/a37d4836519517bdce6cb9d956092321eca3e73b/example.c&#34;&gt;example.c&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;search for &amp;ldquo;Error handling in libpng is done through&amp;rdquo;  in &lt;a href=&#34;https://github.com/glennrp/libpng/blob/libpng16/libpng-manual.txt&#34;&gt;the manual&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For more on setjmp/longjmp in general:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://en.wikipedia.org/wiki/Setjmp.h&#34;&gt;https://en.wikipedia.org/wiki/Setjmp.h&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://web.eecs.utk.edu/~huangj/cs360/360/notes/Setjmp/lecture.html&#34;&gt;https://web.eecs.utk.edu/~huangj/cs360/360/notes/Setjmp/lecture.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://stackoverflow.com/questions/1692814/exception-handling-in-c-what-is-the-use-of-setjmp-returning-0&#34;&gt;https://stackoverflow.com/questions/1692814/exception-handling-in-c-what-is-the-use-of-setjmp-returning-0&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://stackoverflow.com/questions/14685406/practical-usage-of-setjmp-and-longjmp-in-c&#34;&gt;https://stackoverflow.com/questions/14685406/practical-usage-of-setjmp-and-longjmp-in-c&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://stackoverflow.com/questions/7334595/longjmp-out-of-signal-handler&#34;&gt;https://stackoverflow.com/questions/7334595/longjmp-out-of-signal-handler&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://tratt.net/laurie/blog/2005/timing_setjmp_and_the_joy_of_standards.html&#34;&gt;https://tratt.net/laurie/blog/2005/timing_setjmp_and_the_joy_of_standards.html&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;That said, to side step all of this the choices appear to be to using those aforementioned &amp;ldquo;Simplified libpng API&amp;rdquo; (No examples of that in this repo, only indexed colors), which return UInt32 error codes.&lt;/p&gt;
&lt;h4 id=&#34;why-not-just-use-custom-error-functions&#34;&gt;Why not just use custom error functions?&lt;/h4&gt;
&lt;p&gt;Well, this code tries but it doesn&amp;rsquo;t end up with anything that useful.&lt;/p&gt;
&lt;p&gt;Setting the error functions in the &lt;code&gt;png_create_*_struct&lt;/code&gt; functions, i.e.  &lt;code&gt;(png_voidp)user_error_ptr, user_error_fn, user_warning_fn)&lt;/code&gt; is not common in example code, but can be done. However, these functions STILL need to have &lt;code&gt;jmpdef&lt;/code&gt;&amp;rsquo;s in them to leave &lt;code&gt;libpng&lt;/code&gt;&amp;rsquo;s handling function so they are not a way to avoid &lt;code&gt;jmpdef&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;From the manual, the warning functions passes to &lt;code&gt;png_create_*_struct&lt;/code&gt; should be of the formats:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;void&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;user_error_fn&lt;/span&gt;(png_structp png_ptr,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        png_const_charp error_msg);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;void&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;user_warning_fn&lt;/span&gt;(png_structp png_ptr,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        png_const_charp warning_msg);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//Then, within your user_error_fn or user_warning_fn, you can retrieve
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//the error_ptr if you need it, by calling
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    png_voidp error_ptr &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;png_get_error_ptr&lt;/span&gt;(png_ptr);
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;After initialization &lt;code&gt;png_set_error_fn&lt;/code&gt; can be used after struct init to update what error function should be used.&lt;/p&gt;
&lt;p&gt;For an idea of the type of strings the &lt;code&gt;error_fn&lt;/code&gt; and &lt;code&gt;warning_fn&lt;/code&gt; try browsing the results of a &lt;a href=&#34;https://github.com/glennrp/libpng/search?q=png_error&amp;amp;type=code&#34;&gt;search for png_error&lt;/a&gt; or &lt;a href=&#34;https://github.com/glennrp/libpng/search?q=png_warning&amp;amp;type=code&#34;&gt;png_warning&lt;/a&gt; in the libpng github repo.&lt;/p&gt;
&lt;p&gt;Examples:
- &lt;a href=&#34;https://github.com/glennrp/libpng/blob/a37d4836519517bdce6cb9d956092321eca3e73b/contrib/visupng/PngFile.c&#34;&gt;https://github.com/glennrp/libpng/blob/a37d4836519517bdce6cb9d956092321eca3e73b/contrib/visupng/PngFile.c&lt;/a&gt;
- &lt;a href=&#34;https://github.com/glennrp/libpng/blob/5f5f98a1a919e89f0bcea26d73d96dec760f222f/contrib/libtests/timepng.c&#34;&gt;https://github.com/glennrp/libpng/blob/5f5f98a1a919e89f0bcea26d73d96dec760f222f/contrib/libtests/timepng.c&lt;/a&gt;
- &lt;a href=&#34;https://github.com/glennrp/libpng/blob/61bfdb0cb02a6f3a62c929dbc9e832894c0a8df2/contrib/libtests/pngvalid.c&#34;&gt;https://github.com/glennrp/libpng/blob/61bfdb0cb02a6f3a62c929dbc9e832894c0a8df2/contrib/libtests/pngvalid.c&lt;/a&gt;
- &lt;a href=&#34;https://github.com/glennrp/libpng/blob/a37d4836519517bdce6cb9d956092321eca3e73b/contrib/gregbook/writepng.c&#34;&gt;https://github.com/glennrp/libpng/blob/a37d4836519517bdce6cb9d956092321eca3e73b/contrib/gregbook/writepng.c&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The addition of an ErrorPointer struct that could hold needed information to pass the the error function can help with clean up. The error_ptr is a &lt;code&gt;void*&lt;/code&gt;, as long as YOU know what it is, it can be whatever you need.&lt;/p&gt;
&lt;p&gt;If the user will just leave the program at this point missing a dealloc may not the biggest deal, but file IO and network might not be closed, so be sure to check.&lt;/p&gt;
&lt;p&gt;If your callback nopes out with an &lt;code&gt;exit&lt;/code&gt; or &lt;code&gt;abort&lt;/code&gt;, this &amp;ldquo;Quitting behavior&amp;rdquo; will prevent being accepted into the app store. That&amp;rsquo;s also no better than libpng default, so almost might as well have left it nil.&lt;/p&gt;
&lt;p&gt;the &lt;code&gt;buildSimpleDataExample&lt;/code&gt; calls a working, but not super useful, callback example.&lt;/p&gt;
&lt;h3 id=&#34;why-doesnt-the-idat-look-like-the-pixels-that-were-passed-inout-of-libpng&#34;&gt;Why doesn&amp;rsquo;t the IDAT look like the pixels that were passed in/out of libpng?&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;TODO: write about filter types
&lt;a href=&#34;http://www.libpng.org/pub/png/book/chapter09.html&#34;&gt;http://www.libpng.org/pub/png/book/chapter09.html&lt;/a&gt;
None     Each byte is unchanged.
Sub     Each byte is replaced with the difference between it and the ``corresponding byte&amp;rsquo;&amp;rsquo; to its left.
Up     Each byte is replaced with the difference between it and the byte above it (in the previous row, as it was before filtering).
Average     Each byte is replaced with the difference between it and the average of the corresponding bytes to its left and above it, truncating any fractional part.
Paeth     Each byte is replaced with the difference between it and the Paeth predictor of the corresponding bytes to its left, above it, and to its upper left.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;why-does-the-writing-example-use-data-instead-of-uint8&#34;&gt;Why does the writing example use Data instead of [UInt8]?&lt;/h3&gt;
&lt;p&gt;When trying to write cross-platform code, I tend to try to use the lowest level type as much as possible to move information around. In this case using a &lt;code&gt;[UInt8]&lt;/code&gt; over a &lt;code&gt;Data&lt;/code&gt; would cost so much additional overhead, it&amp;rsquo;s not currently worth the hassle.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;UnsafeMutableRawPointer&lt;/code&gt; pointer returned from &lt;code&gt;png_get_io_ptr&lt;/code&gt; always points to the data structure&amp;rsquo;s head, whether a file or Data, or something else, not to a cursor location where new Data should be written to. If the &lt;code&gt;buildSimpleDataExample&lt;/code&gt; function and it&amp;rsquo;s &lt;code&gt;writeDataCallback&lt;/code&gt; callback were embedded in a class, then one could potentially make a class variable that holds &amp;ldquo;whats my IO curser offset?&amp;rdquo; information for the callback function to refer to.&lt;/p&gt;
&lt;p&gt;But &lt;code&gt;buildSimpleDataExample&lt;/code&gt; is not in a class or even a struct instance! So what is a lone little static function to do?&lt;/p&gt;
&lt;p&gt;The good news is that &lt;code&gt;Data&lt;/code&gt; is magic. &lt;code&gt;Data&lt;/code&gt; (unlike say &lt;code&gt;[UInt8]&lt;/code&gt;) has &lt;a href=&#34;https://github.com/apple/swift-corelibs-foundation/blob/eec4b26deee34edb7664ddd9c1222492a399d122/Sources/Foundation/Data.swift&#34;&gt;private size variables allocated with it&lt;/a&gt;. This means it can implement &lt;code&gt;func append(_ bytes: UnsafeRawPointer, length: Int)&lt;/code&gt;&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    @inlinable &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// This is @inlinable as it does not escape the _DataStorage boundary layer.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;append&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; bytes: UnsafeRawPointer, length: &lt;span style=&#34;color:#91d7e3&#34;&gt;Int&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#91d7e3&#34;&gt;precondition&lt;/span&gt;(length &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;gt;=&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;0&lt;/span&gt;, &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Length of appending bytes must not be negative&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;origLength&lt;/span&gt; = _length
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;newLength&lt;/span&gt; = origLength &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;+&lt;/span&gt; length
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; _capacity &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;lt;&lt;/span&gt; newLength &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;||&lt;/span&gt; _bytes == &lt;span style=&#34;color:#f5a97f&#34;&gt;nil&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            ensureUniqueBufferReference(growingTo: newLength, clear: &lt;span style=&#34;color:#f5a97f&#34;&gt;false&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        _length = newLength
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        __DataStorage.move(_bytes!.advanced(by: origLength), bytes, length)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The existence of this function means we can append when all we have is a pointer. It&amp;rsquo;s amazing.&lt;/p&gt;
&lt;p&gt;The &lt;a href=&#34;https://stackoverflow.com/questions/1821806/how-to-encode-png-to-buffer-using-libpng&#34;&gt;example C code&lt;/a&gt;  floating around the internet for writing to a buffer is:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//Make a new compound type that stores the pointer and the cursor location/size
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;struct&lt;/span&gt; mem_encode
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#ed8796&#34;&gt;char&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;*&lt;/span&gt;buffer;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#ed8796&#34;&gt;size_t&lt;/span&gt; size;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;void&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;my_png_write_data&lt;/span&gt;(png_structp png_ptr, png_bytep data, &lt;span style=&#34;color:#ed8796&#34;&gt;png_size_t&lt;/span&gt; length)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;/* with libpng15 next line causes pointer deference error; use libpng12 */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#c6a0f6&#34;&gt;struct&lt;/span&gt; mem_encode&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;*&lt;/span&gt; p&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt;(&lt;span style=&#34;color:#c6a0f6&#34;&gt;struct&lt;/span&gt; mem_encode&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;*&lt;/span&gt;)&lt;span style=&#34;color:#8aadf4&#34;&gt;png_get_io_ptr&lt;/span&gt;(png_ptr); &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;/* was png_ptr-&amp;gt;io_ptr */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#ed8796&#34;&gt;size_t&lt;/span&gt; nsize &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; p&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;-&amp;gt;&lt;/span&gt;size &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;+&lt;/span&gt; length;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;/* allocate or grow buffer */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt;(p&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;-&amp;gt;&lt;/span&gt;buffer)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    p&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;-&amp;gt;&lt;/span&gt;buffer &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;realloc&lt;/span&gt;(p&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;-&amp;gt;&lt;/span&gt;buffer, nsize);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#c6a0f6&#34;&gt;else&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    p&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;-&amp;gt;&lt;/span&gt;buffer &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;malloc&lt;/span&gt;(nsize);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt;(&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;!&lt;/span&gt;p&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;-&amp;gt;&lt;/span&gt;buffer)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#8aadf4&#34;&gt;png_error&lt;/span&gt;(png_ptr, &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Write Error&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;/* copy new bytes to end of buffer */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#8aadf4&#34;&gt;memcpy&lt;/span&gt;(p&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;-&amp;gt;&lt;/span&gt;buffer &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;+&lt;/span&gt; p&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;-&amp;gt;&lt;/span&gt;size, data, length);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  p&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;-&amp;gt;&lt;/span&gt;size &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;+=&lt;/span&gt; length;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Where you can see that it is implementing by hand that buffer tracking (&lt;code&gt;mem_encode&lt;/code&gt;) and the buffer expansion by hand.&lt;/p&gt;
&lt;p&gt;Thankfully using &lt;code&gt;Data&lt;/code&gt; appears to make all of that unnecessary.&lt;/p&gt;
&lt;h3 id=&#34;simplified-api&#34;&gt;Simplified API&lt;/h3&gt;
&lt;p&gt;There is apparently a simpler API. However, they target &amp;ldquo;in-memory bitmap formats&amp;rdquo; not RGBA, which this project requires.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;A &amp;ldquo;simplified API&amp;rdquo; has been added (see documentation in png.h and a simple
example in contrib/examples/pngtopng.c).  The new publicly visible API
includes the following:&lt;/p&gt;&lt;/blockquote&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;   macros:
     PNG_FORMAT_*
     PNG_IMAGE_*
   structures:
     png_control
     png_image
   read functions
     png_image_begin_read_from_file()
     png_image_begin_read_from_stdio()
     png_image_begin_read_from_memory()
     png_image_finish_read()
     png_image_free()
   write functions
     png_image_write_to_file()
     png_image_write_to_memory()
     png_image_write_to_stdio()
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&#34;if-xcode-is-having-trouble-finding-libpng&#34;&gt;If XCode is having trouble finding libpng&lt;/h2&gt;
&lt;h4 id=&#34;what-does-compiling-in-the-command-line-say&#34;&gt;What does compiling in the command line say?&lt;/h4&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;cd $PROJECT_DIR
swift package clean
swift build --verbose
&lt;/code&gt;&lt;/pre&gt;&lt;h4 id=&#34;is-package-config-installed&#34;&gt;Is &lt;code&gt;package-config&lt;/code&gt; installed?&lt;/h4&gt;
&lt;p&gt;&lt;code&gt;brew install pkg-config&lt;/code&gt;&lt;/p&gt;
&lt;h4 id=&#34;homebrew-path-correct&#34;&gt;Homebrew path correct?&lt;/h4&gt;
&lt;p&gt;When installing homebrew did you update the path? Especially important on M1 macs where the install path has changed to &lt;code&gt;/opt/homebrew/&lt;/code&gt; from &lt;code&gt;/usr/local/include/&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Check &lt;code&gt;cat ~/.zprofile&lt;/code&gt; it should exist and contain &lt;code&gt;eval &amp;quot;$(/opt/homebrew/bin/brew shellenv)&amp;quot;&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;If &lt;code&gt;~/.zprofile&lt;/code&gt; does not exist and contain that line run:
&lt;code&gt;echo &#39;eval &amp;quot;$(/opt/homebrew/bin/brew shellenv)&amp;quot;&#39; &amp;gt;&amp;gt; ~/.zprofile eval $(/opt/homebrew/bin/brew shellenv)&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Commands run:
&lt;code&gt;export HOMEBREW_PREFIX=&amp;quot;/opt/homebrew&amp;quot;; export HOMEBREW_CELLAR=&amp;quot;/opt/homebrew/Cellar&amp;quot;; export HOMEBREW_REPOSITORY=&amp;quot;/opt/homebrew&amp;quot;; export PATH=&amp;quot;/opt/homebrew/bin:/opt/homebrew/sbin${PATH+:$PATH}&amp;quot;; export MANPATH=&amp;quot;/opt/homebrew/share/man${MANPATH+:$MANPATH}:&amp;quot;; export INFOPATH=&amp;quot;/opt/homebrew/share/info:${INFOPATH:-}&amp;quot;;&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;If this command provides no output if it has already been run.&lt;/p&gt;
&lt;p&gt;To check the path: &lt;code&gt;echo $PATH&lt;/code&gt; it should now contain &lt;code&gt;/opt/homebrew/bin:/opt/homebrew/sbin:&lt;/code&gt;&lt;/p&gt;
&lt;h2 id=&#34;build-issues-by-platform&#34;&gt;Build Issues by Platform&lt;/h2&gt;
&lt;p&gt;Have I gotten this library to compile for&amp;hellip;&lt;/p&gt;
&lt;h3 id=&#34;intel-mac&#34;&gt;Intel Mac&lt;/h3&gt;
&lt;p&gt;Yes, totally fine with &lt;code&gt;pkg-config&lt;/code&gt; installed.&lt;/p&gt;
&lt;h3 id=&#34;apple-silicon-mac&#34;&gt;Apple Silicon Mac&lt;/h3&gt;
&lt;p&gt;Yes, totally fine with &lt;code&gt;pkg-config&lt;/code&gt; installed.&lt;/p&gt;
&lt;h3 id=&#34;ios-simulator-no&#34;&gt;iOS Simulator: No&lt;/h3&gt;
&lt;p&gt;Not a high priority to fix.&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;Building for iOS Simulator, but linking in dylib built for macOS, file &amp;#39;/usr/local/opt/libpng/lib/libpng16.dylib&amp;#39; for architecture x86_64
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Options:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://developer.apple.com/forums/thread/657913&#34;&gt;https://developer.apple.com/forums/thread/657913&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://stackoverflow.com/questions/63607158/xcode-building-for-ios-simulator-but-linking-in-an-object-file-built-for-ios-f&#34;&gt;https://stackoverflow.com/questions/63607158/xcode-building-for-ios-simulator-but-linking-in-an-object-file-built-for-ios-f&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://www.dynamsoft.com/barcode-reader/docs/mobile//programming/objectivec-swift/faq/arm64-simulator-error.html&#34;&gt;https://www.dynamsoft.com/barcode-reader/docs/mobile//programming/objectivec-swift/faq/arm64-simulator-error.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://rlaguilar.com/posts/integrate-c-library-ios-project-swift/&#34;&gt;https://rlaguilar.com/posts/integrate-c-library-ios-project-swift/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://thisisyuu.github.io/2020/MISC-Building-universal-binaries-from-C-library-for-an-iOS-project/&#34;&gt;https://thisisyuu.github.io/2020/MISC-Building-universal-binaries-from-C-library-for-an-iOS-project/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;ios-hardware-no&#34;&gt;iOS Hardware: No&lt;/h3&gt;
&lt;p&gt;Not a high priority to fix.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Linker command failed with exit code 1 (use -v to see invocation)&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Related to above.&lt;/p&gt;
&lt;h3 id=&#34;fake-linux-github-action---not-yet&#34;&gt;Fake Linux (Github Action) - Not yet&lt;/h3&gt;
&lt;p&gt;Higer priority to fix.&lt;/p&gt;
&lt;p&gt;Use action like one checking &lt;a href=&#34;https://github.com/carlynorama/APItizer/actions&#34;&gt;APITizer&lt;/a&gt;&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-yml&#34; data-lang=&#34;yml&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;name&lt;/span&gt;: Build Linux
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;on&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#c6a0f6&#34;&gt;push&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;branches&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      - &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#39;*&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#c6a0f6&#34;&gt;pull_request&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;branches&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      - main
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;jobs&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#c6a0f6&#34;&gt;build&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;name&lt;/span&gt;: Build Linux
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;runs-on&lt;/span&gt;: ubuntu-latest
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;container&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#c6a0f6&#34;&gt;image&lt;/span&gt;: swift:latest
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;steps&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      - &lt;span style=&#34;color:#c6a0f6&#34;&gt;name&lt;/span&gt;: Checkout
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;uses&lt;/span&gt;: actions/checkout@v3
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      - &lt;span style=&#34;color:#c6a0f6&#34;&gt;name&lt;/span&gt;: Build Linux framework
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;run&lt;/span&gt;: |&lt;span style=&#34;color:#6e738d&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d&#34;&gt;           swift build
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d&#34;&gt;           swift test&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      - &lt;span style=&#34;color:#c6a0f6&#34;&gt;name&lt;/span&gt;: Build Linux Demo
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;run&lt;/span&gt;: |&lt;span style=&#34;color:#6e738d&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d&#34;&gt;            cd Demo/Demo\ Ubuntu
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d&#34;&gt;            swift build&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This one fails with &lt;code&gt;warning: you may be able to install libpng using your system-packager:apt-get install libpng-dev&lt;/code&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;TODO: figure out how to make one that works. (may also have to install pkg-config)&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;the-swift-code&#34;&gt;The Swift Code&lt;/h2&gt;
&lt;p&gt;So far the library isn&amp;rsquo;t that big, so here&amp;rsquo;s a copy of the code&lt;/p&gt;
&lt;h3 id=&#34;struct-declaration&#34;&gt;Struct declaration&lt;/h3&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-Swift&#34; data-lang=&#34;Swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#if&lt;/span&gt; &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;os&lt;/span&gt;(&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;Linux&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;Glibc&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#else&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;Darwin&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#endif&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;Foundation&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;png&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;SwiftLIBPNG&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//http://www.libpng.org/pub/png/book/chapter08.html#png.ch08.tbl.1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;pngFileSignature&lt;/span&gt;:[&lt;span style=&#34;color:#91d7e3&#34;&gt;UInt8&lt;/span&gt;] = [&lt;span style=&#34;color:#f5a97f&#34;&gt;0x89&lt;/span&gt;, &lt;span style=&#34;color:#f5a97f&#34;&gt;0x50&lt;/span&gt;, &lt;span style=&#34;color:#f5a97f&#34;&gt;0x4E&lt;/span&gt;, &lt;span style=&#34;color:#f5a97f&#34;&gt;0x47&lt;/span&gt;, &lt;span style=&#34;color:#f5a97f&#34;&gt;0x0D&lt;/span&gt;, &lt;span style=&#34;color:#f5a97f&#34;&gt;0x0A&lt;/span&gt;, &lt;span style=&#34;color:#f5a97f&#34;&gt;0x1A&lt;/span&gt;, &lt;span style=&#34;color:#f5a97f&#34;&gt;0x0A&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;init&lt;/span&gt;() {}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;version&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;version&lt;/span&gt; = png_access_version_number()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(version)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;versionInfo&lt;/span&gt;()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;test2&lt;/span&gt; = &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;(format:&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;   Compiled with libpng %@; using libpng %lu.&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\n&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;, PNG_LIBPNG_VER_STRING, png_access_version_number())
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(test2)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;checkSignature&lt;/span&gt;(data:Data, offset:&lt;span style=&#34;color:#91d7e3&#34;&gt;Int&lt;/span&gt; = &lt;span style=&#34;color:#f5a97f&#34;&gt;0&lt;/span&gt;) -&amp;gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;Bool&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        withUnsafeBytes(of:data) { bytesPtr &lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;base&lt;/span&gt; = bytesPtr.assumingMemoryBound(to: &lt;span style=&#34;color:#91d7e3&#34;&gt;UInt8&lt;/span&gt;.&lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;).baseAddress {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; isValidSignature(bytePointer: base &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;+&lt;/span&gt; offset, start: &lt;span style=&#34;color:#f5a97f&#34;&gt;0&lt;/span&gt;, &lt;span style=&#34;color:#91d7e3&#34;&gt;count&lt;/span&gt;: &lt;span style=&#34;color:#f5a97f&#34;&gt;8&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            } &lt;span style=&#34;color:#c6a0f6&#34;&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;false&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;isValidSignature&lt;/span&gt;(bytePointer:&lt;span style=&#34;color:#91d7e3&#34;&gt;UnsafePointer&lt;/span&gt;&amp;lt;&lt;span style=&#34;color:#91d7e3&#34;&gt;UInt8&lt;/span&gt;&amp;gt;, start:&lt;span style=&#34;color:#91d7e3&#34;&gt;Int&lt;/span&gt; = &lt;span style=&#34;color:#f5a97f&#34;&gt;0&lt;/span&gt;, &lt;span style=&#34;color:#91d7e3&#34;&gt;count&lt;/span&gt;:&lt;span style=&#34;color:#91d7e3&#34;&gt;CInt&lt;/span&gt;) -&amp;gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;Bool&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//png_sig_cmp(T##sig: png_const_bytep!##png_const_bytep!, T##start: Int##Int, T##num_to_check: Int##Int)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; png_sig_cmp(bytePointer, start, &lt;span style=&#34;color:#f5a97f&#34;&gt;8&lt;/span&gt;) == &lt;span style=&#34;color:#f5a97f&#34;&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;printIOState&lt;/span&gt;(pngPointer:OpaquePointer) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//        /* The flags returned by png_get_io_state() are the following: */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//        #  define PNG_IO_NONE        0x0000   /* no I/O at this moment */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//        #  define PNG_IO_READING     0x0001   /* currently reading */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//        #  define PNG_IO_WRITING     0x0002   /* currently writing */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//        #  define PNG_IO_SIGNATURE   0x0010   /* currently at the file signature */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//        #  define PNG_IO_CHUNK_HDR   0x0020   /* currently at the chunk header */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//        #  define PNG_IO_CHUNK_DATA  0x0040   /* currently at the chunk data */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//        #  define PNG_IO_CHUNK_CRC   0x0080   /* currently at the chunk crc */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//        #  define PNG_IO_MASK_OP     0x000f   /* current operation: reading/writing */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//        #  define PNG_IO_MASK_LOC    0x00f0   /* current location: sig/hdr/data/crc */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//        #endif /* IO_STATE */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;codeString&lt;/span&gt;:&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt; = &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;(&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;(&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;(png_get_io_state(pngPointer), radix:&lt;span style=&#34;color:#f5a97f&#34;&gt;2&lt;/span&gt;).reversed()).padding(toLength: &lt;span style=&#34;color:#f5a97f&#34;&gt;8&lt;/span&gt;, withPad: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;0&amp;#34;&lt;/span&gt;, startingAt: &lt;span style=&#34;color:#f5a97f&#34;&gt;0&lt;/span&gt;).reversed())
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//1000010 -&amp;gt; currently writing at the chunk header&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//1000010 -&amp;gt; currently writing at the chunk crc&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(codeString)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;MARK:&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt; Global Error Callbacks&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;PNGErrorInfo&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;png_ptr&lt;/span&gt;:OpaquePointer?
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;info_ptr&lt;/span&gt;:OpaquePointer?
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;fileHandle&lt;/span&gt;:&lt;span style=&#34;color:#91d7e3&#34;&gt;UnsafeMutablePointer&lt;/span&gt;&amp;lt;FILE&amp;gt;?
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;testExtraData&lt;/span&gt;:&lt;span style=&#34;color:#91d7e3&#34;&gt;UInt32&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;print_info&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;(&lt;/span&gt;describing: png_ptr&lt;span style=&#34;color:#a6da95&#34;&gt;))&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;, &lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;(&lt;/span&gt;describing: info_ptr&lt;span style=&#34;color:#a6da95&#34;&gt;))&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;, &lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;(&lt;/span&gt;describing: fileHandle&lt;span style=&#34;color:#a6da95&#34;&gt;))&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;, &lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;testExtraData&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;writeErrorCallback&lt;/span&gt;:@convention(c) (&lt;span style=&#34;color:#91d7e3&#34;&gt;Optional&lt;/span&gt;&amp;lt;OpaquePointer&amp;gt;, &lt;span style=&#34;color:#91d7e3&#34;&gt;Optional&lt;/span&gt;&amp;lt;&lt;span style=&#34;color:#91d7e3&#34;&gt;UnsafePointer&lt;/span&gt;&amp;lt;&lt;span style=&#34;color:#91d7e3&#34;&gt;CChar&lt;/span&gt;&amp;gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;gt;&lt;/span&gt;) -&amp;gt; () = { png_ptr, message &lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;error_ptr&lt;/span&gt; = png_get_error_ptr(png_ptr) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;There was a non nil error pointer set a &lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;error_ptr&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;typed_error_ptr&lt;/span&gt; = error_ptr.load(&lt;span style=&#34;color:#c6a0f6&#34;&gt;as&lt;/span&gt;: PNGErrorInfo.&lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;)&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//error_ptr.assumingMemoryBound(to: PNGErrorInfo.self)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            typed_error_ptr.print_info()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//If aborting whole program everything should be freed automatically, but in case not...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#91d7e3&#34;&gt;precondition&lt;/span&gt;(png_ptr == typed_error_ptr.png_ptr)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            png_destroy_write_struct(&amp;amp;typed_error_ptr.png_ptr, &amp;amp;typed_error_ptr.info_ptr)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; typed_error_ptr.fileHandle &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;!=&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;nil&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                fclose(typed_error_ptr.fileHandle)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;message&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;libpng crashed with warning: &lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;(&lt;/span&gt;cString: message&lt;span style=&#34;color:#a6da95&#34;&gt;))&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        } &lt;span style=&#34;color:#c6a0f6&#34;&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;libpng crashed without providing a message.&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//Some way to kill png?&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//How to leave PNG write...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        exit(&lt;span style=&#34;color:#f5a97f&#34;&gt;99&lt;/span&gt;)  &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//see also https://en.cppreference.com/w/c/program/atexit&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//abort() //terminates the process by raising a SIGABRT signal, possible handler?&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;writeWarningCallback&lt;/span&gt;:@convention(c) (&lt;span style=&#34;color:#91d7e3&#34;&gt;Optional&lt;/span&gt;&amp;lt;OpaquePointer&amp;gt;, &lt;span style=&#34;color:#91d7e3&#34;&gt;Optional&lt;/span&gt;&amp;lt;&lt;span style=&#34;color:#91d7e3&#34;&gt;UnsafePointer&lt;/span&gt;&amp;lt;&lt;span style=&#34;color:#91d7e3&#34;&gt;CChar&lt;/span&gt;&amp;gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;gt;&lt;/span&gt;) -&amp;gt; () = { png_ptr, message &lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;error_ptr&lt;/span&gt; = png_get_error_ptr(png_ptr) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;There was a non nil error pointer set a &lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;error_ptr&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;message&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;libpng sends warning: &lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;(&lt;/span&gt;cString: message&lt;span style=&#34;color:#a6da95&#34;&gt;))&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        } &lt;span style=&#34;color:#c6a0f6&#34;&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;libpng sends unspecified warning&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//Use the error pointer to set flags, etc.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;errors&#34;&gt;Errors&lt;/h3&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;enum PNGError: Error, CustomStringConvertible {
    case message(String)
    case outOfMemory
    
    public var description: String {
        switch self {
        case let .message(message): return message
        case .outOfMemory:
            return &amp;#34;Out of Memory&amp;#34;
        }
    }
    init(_ message: String) {
        self = .message(message)
    }
}
&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=&#34;reading&#34;&gt;Reading&lt;/h3&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-Swift&#34; data-lang=&#34;Swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#if&lt;/span&gt; &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;os&lt;/span&gt;(&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;Linux&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;Glibc&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#else&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;Darwin&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#endif&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;png&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//http://www.libpng.org/pub/png/libpng-manual.txt&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// Text with //DOC: prefix is from the documentation above.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;extension&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;SwiftLIBPNG&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;TODO:&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt; This code (is expected to) hard crash if the file is not a valid PNG. Default error handling is stderr and ABORT.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//NOT using &amp;#34;libpng simplified API&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;simpleFileRead&lt;/span&gt;(from path:&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;) &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; -&amp;gt; [&lt;span style=&#34;color:#91d7e3&#34;&gt;UInt8&lt;/span&gt;] {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;file_ptr&lt;/span&gt; = fopen(path, &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;r&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; file_ptr == &lt;span style=&#34;color:#f5a97f&#34;&gt;nil&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;throw&lt;/span&gt; PNGError(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;File pointer not available&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//Make the pointer for storing the png&amp;#39;s current state struct.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//Using this function tells libpng to expect to handle memory management, but `png_destroy_read_struct` will still need to be called.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//takes the version string define, and some pointers that will override rides to default error handling that are not used in this simple case.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;/*C:-- png_create_read_struct(
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;         user_png_ver: png_const_charp!,
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;         error_ptr: png_voidp!,
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;         error_fn: png_error_ptr! (png_structp?, png_const_charp?) -&amp;gt; Void,
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;         warn_fn: png_error_ptr!  (png_structp?, png_const_charp?) -&amp;gt; Void)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;         */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;png_ptr&lt;/span&gt;:OpaquePointer? = png_create_read_struct(PNG_LIBPNG_VER_STRING, &lt;span style=&#34;color:#f5a97f&#34;&gt;nil&lt;/span&gt;, &lt;span style=&#34;color:#f5a97f&#34;&gt;nil&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                                                            &lt;span style=&#34;color:#f5a97f&#34;&gt;nil&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; (png_ptr == &lt;span style=&#34;color:#f5a97f&#34;&gt;nil&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            fclose(file_ptr);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;throw&lt;/span&gt; PNGError.outOfMemory
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//Makes the pointer to handle information about how the underlying PNG data needs to be manipulated.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//C:-- png_create_info_struct(png_const_structrp!)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;info_ptr&lt;/span&gt;:OpaquePointer? = png_create_info_struct(png_ptr);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; (info_ptr == &lt;span style=&#34;color:#f5a97f&#34;&gt;nil&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            png_destroy_read_struct(&amp;amp;png_ptr, &lt;span style=&#34;color:#f5a97f&#34;&gt;nil&lt;/span&gt;, &lt;span style=&#34;color:#f5a97f&#34;&gt;nil&lt;/span&gt;); &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;TODO:&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt; not all examples do this&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;throw&lt;/span&gt; PNGError.outOfMemory;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//## Why no setjmp?? - see README&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;     
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//set destination pointer and file source pointer&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//C:-- png_init_io(png_ptr: png_structrp!, fp: png_FILE_p!)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        png_init_io(png_ptr, file_ptr);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//If you don&amp;#39;t want to use fileio , can instead&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;/*C:-- png_set_read_fn(
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;         png_ptr: png_structrp!,
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;         io_ptr: png_voidp!,
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;         read_data_fn: png_rw_ptr! (png_structp?, png_bytep?, Int) -&amp;gt; Void)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;         */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;TODO:&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;(see write for example)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//Optional: If you used the file stream already and pulled off the file signature for verification purposes, tell the reader it&amp;#39;s been done already.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//png_set_sig_bytes(png_ptr, number);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//Optional: One can also decide how to handle CRC errors (possible bad chunks. )&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//png_set_crc_action(png_ptr, crit_action, ancil_action);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//Other Options: Setting size limits, how to handle chunks that are not defined by the spec&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//Optional: Set a row-completion handler&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//`pointer` is the png_ptr&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//`row` is the NEXT row number&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//`pass` is always 0 in non interlaced pngs, but also refers to the NEXT row&amp;#39;s pass count.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;rowCompleteCallback&lt;/span&gt;:@convention(c) (OpaquePointer?, &lt;span style=&#34;color:#91d7e3&#34;&gt;UInt32&lt;/span&gt;, &lt;span style=&#34;color:#91d7e3&#34;&gt;Int32&lt;/span&gt;) -&amp;gt; () = { png_ptr, row, pass &lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(png_ptr ?? &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;nil&amp;#34;&lt;/span&gt;, row, pass)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        png_set_read_status_fn(png_ptr, rowCompleteCallback);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//Optional: Do a lot of setting of gamma and alpha handling for your system.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//Possibly overridden by PNG settings, in some situations.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//No example code provided.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//This is a SIMPLE read. Assumes&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//- the entire file can be _all_ loaded into memory, all at once&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//- that this can be done before any header info needed&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//- don&amp;#39;t want to malloc your own row storage&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//- don&amp;#39;t need to do successive transforms on the data at read in&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//- any transform you want to do has PNG_TRANSFORM_ define&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//Set what transforms desired. If any&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;TODO:&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt; Bit print out of masks.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;png_transforms&lt;/span&gt; = PNG_TRANSFORM_IDENTITY &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//No transforms&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//DOC: This call is equivalent to png_read_info(), followed the set of transformations indicated by the transform mask, then png_read_image(), and finally png_read_end().&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        png_read_png(png_ptr, info_ptr, png_transforms, &lt;span style=&#34;color:#f5a97f&#34;&gt;nil&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//DOC: If you don&amp;#39;t allocate row_pointers ahead of time, png_read_png() will do it, and it&amp;#39;ll be free&amp;#39;ed by libpng when you call png_destroy_*().&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;row_pointers&lt;/span&gt; = png_get_rows(png_ptr, info_ptr)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;TODO:&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt; What happens to end info if no end_info struct? Double make sure is in info_ptr. (doc says it will be.)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;width&lt;/span&gt; = png_get_image_width(png_ptr,info_ptr)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;height&lt;/span&gt; = png_get_image_height(png_ptr,info_ptr)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;color_type_code&lt;/span&gt; = png_get_color_type(png_ptr, info_ptr)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;bit_depth&lt;/span&gt; = png_get_bit_depth(png_ptr, info_ptr)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;channel_count&lt;/span&gt; = png_get_channels(png_ptr, info_ptr)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;row_byte_width&lt;/span&gt; = png_get_rowbytes(png_ptr, info_ptr)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&amp;#34;&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;                width: &lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;width&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;                height: &lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;height&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;                colorType: &lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;color_type_code&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;                bitDepth: &lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;bit_depth&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;                channelCount: &lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;channel_count&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;                rowByteWidth: &lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;row_byte_width&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;        &amp;#34;&amp;#34;&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//let pixel_width = channelCountFor(colorTypeCode: color_type_code) * UInt32(bit_depth)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;imagePixels&lt;/span&gt;:[&lt;span style=&#34;color:#91d7e3&#34;&gt;UInt8&lt;/span&gt;] = []
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;imageRows&lt;/span&gt; = &lt;span style=&#34;color:#91d7e3&#34;&gt;UnsafeBufferPointer&lt;/span&gt;(start: row_pointers, &lt;span style=&#34;color:#91d7e3&#34;&gt;count&lt;/span&gt;: &lt;span style=&#34;color:#91d7e3&#34;&gt;Int&lt;/span&gt;(height))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;for&lt;/span&gt; rowPointer &lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt; imageRows {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;rowBufferPtr&lt;/span&gt; = &lt;span style=&#34;color:#91d7e3&#34;&gt;UnsafeBufferPointer&lt;/span&gt;(start: rowPointer, &lt;span style=&#34;color:#91d7e3&#34;&gt;count&lt;/span&gt;: row_byte_width)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            imagePixels.append(contentsOf: rowBufferPtr)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//-------------------------------------------------------   PNG CLEANUP&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//if set end_info nuke that too. DO NOT free row_pointers since used `png_get_rows`&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        png_destroy_read_struct(&amp;amp;png_ptr, &amp;amp;info_ptr, &lt;span style=&#34;color:#f5a97f&#34;&gt;nil&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        fclose(file_ptr)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//---------------------------------------------------------------------&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; imagePixels
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;writing&#34;&gt;Writing&lt;/h3&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;#if os(Linux)
import Glibc
#else
import Darwin
#endif

import Foundation

import png


extension SwiftLIBPNG {
    // EXAMPLE USAGE
    //    func writeImage() {
    //        let width = 5
    //        let height = 3
    //        var pixelData:[UInt8] = []
    //
    //        for _ in 0..&amp;lt;height {
    //            for _ in 0..&amp;lt;width {
    //                pixelData.append(0x77)
    //                pixelData.append(0x00)
    //                pixelData.append(UInt8.random(in: 0...UInt8.max))
    //                pixelData.append(0xFF)
    //            }
    //        }
    //
    //        let data = try? SwiftLIBPNG.buildSimpleDataExample(width: 5, height: 3, pixelData: pixelData)
    //        if let data {
    //            for item in data {
    //                print(String(format: &amp;#34;0x%02x&amp;#34;, item), terminator: &amp;#34;\t&amp;#34;)
    //            }
    //            print()
    //
    //            let locationToWrite = URL.documentsDirectory.appendingPathComponent(&amp;#34;testImage&amp;#34;, conformingTo: .png)
    //            do {
    //                try data.write(to: locationToWrite)
    //            } catch {
    //                print(error.self)
    //            }
    //        }
    //    }
    
    //NOT using &amp;#34;libpng simplified API&amp;#34;
    //takes a width, height and pixel data in RR GG BB AA byte order
    public static func buildSimpleDataExample(width:UInt32, height:UInt32, pixelData:[UInt8]) throws -&amp;gt; Data {
        var pixelsCopy = pixelData //TODO: This or inout? OR... is there away around need for MutableCopy?
        
        //-----------------------------  INTENTIONAL ERROR
        let bitDepth:UInt8 = 1 //should be 8 (1 byte, values 1, 2, 4, 8, or 16) (has to be 8 or 16 for RGBA)
        //-----------------------------  END INTENTIONAL ERROR
        let colorType = PNG_COLOR_TYPE_RGBA //UInt8(6), (1 byte, values 0, 2, 3, 4, or 6) (6 == red, green, blue and alpha)
        
        
        var pngIOBuffer = Data() //:[UInt8] = [] // //
        withUnsafePointer(to: pngIOBuffer) { print(&amp;#34;io buffer declared: \($0)&amp;#34;) }
        
        var pngWriteErrorInfo = PNGErrorInfo(testExtraData: 42)
        
        //Make the pointer for storing the png&amp;#39;s current state struct.
        //Using this function tells libpng to expect to handle memory management, but `png_destroy_write_struct` will still need to be called.
        //takes the version string define, and some pointers that will override rides to default error handling that are not used in this simple case.
        /*C:-- png_create_write_struct(
         user_png_ver: png_const_charp!,
         error_ptr: png_voidp!,  //safe to leave as nil if you don&amp;#39;t need to pass a message to your error funcs.
         error_fn: png_error_ptr! (png_structp?, png_const_charp?) -&amp;gt; Void,
         warn_fn: png_error_ptr!  (png_structp?, png_const_charp?) -&amp;gt; Void)
         */
        var png_ptr:OpaquePointer? = png_create_write_struct(PNG_LIBPNG_VER_STRING, &amp;amp;pngWriteErrorInfo, writeErrorCallback, writeWarningCallback)
        if (png_ptr == nil) { throw PNGError.outOfMemory }
        
        //Makes the pointer to handle information about how the underlying PNG data needs to be manipulated.
        //C:-- png_create_info_struct(png_const_structrp!)
        var info_ptr:OpaquePointer? = png_create_info_struct(png_ptr);
        if (info_ptr == nil) {
            png_destroy_write_struct(&amp;amp;png_ptr, nil);
            throw PNGError.outOfMemory;
        }
        
        pngWriteErrorInfo.fileHandle = nil
        pngWriteErrorInfo.png_ptr = png_ptr
        pngWriteErrorInfo.info_ptr = info_ptr
        
        //see README for notes on jmpdef
        
        //If writing palletized PNG, see documentation if want to change
        //default palette checking behavior.
        
        //Set the output destination. If writing to file can use png_init_io(png_ptr, file_ptr); as in simpleFileRead or, one can construct a data receiving function and set it with:
        /*C:--png_set_write_fn(
         png_ptr: png_structrp!,
         io_ptr: png_voidp!,
         write_data_fn: png_rw_ptr! (png_structp?, png_bytep?, Int) -&amp;gt; Void,
         output_flush_fn: png_flush_ptr! (png_structp?) -&amp;gt; Void
         )
         */
        
        let writeDataCallback: @convention(c) (Optional&amp;lt;OpaquePointer&amp;gt;, Optional&amp;lt;UnsafeMutablePointer&amp;lt;UInt8&amp;gt;&amp;gt;, Int) -&amp;gt; Void = { png_ptr, data_io_ptr, length in
            guard let output_ptr:UnsafeMutableRawPointer = png_get_io_ptr(png_ptr) else { return }
            guard let data_ptr:UnsafeMutablePointer&amp;lt;UInt8&amp;gt; = data_io_ptr else { return }
            //print(&amp;#34;callback io output buffer: \(output_ptr)&amp;#34;)
            //print(&amp;#34;callback io data buffer: \(data_ptr)&amp;#34;)
            
            let typed_output_ptr = output_ptr.assumingMemoryBound(to: Data.self)
            typed_output_ptr.pointee.append(data_ptr, count: length)
        }
        
        png_set_write_fn(png_ptr, &amp;amp;pngIOBuffer, writeDataCallback, nil)
        
        //if have already handled appending header or otherwise don&amp;#39;t need to.
        //png_set_sig_bytes(png_ptr, 8);
        
        //Optional: Set a row-completion handler
        //`pointer` is the png_ptr
        //`row` is the NEXT row number
        //`pass` is always 0 in non interlaced pngs, but also refers to the NEXT row&amp;#39;s pass count.
        //READ example uses callback, but also takes closure.
        png_set_write_status_fn(png_ptr) { png_ptr, row, pass in
            print(png_ptr ?? &amp;#34;nil&amp;#34;, row, pass)
        }
        
        //Set compression schemes. Don&amp;#39;t call to leave as the default. libpng optimizes for a good balance between writing speed and resulting file compression.
        //NOTE: If you need the data &amp;#34;as is&amp;#34;, that is not the default scheme.
        //http://www.libpng.org/pub/png/book/chapter09.html
        //https://www.ietf.org/rfc/rfc1951.txt
        //C:--png_set_filter(png_ptr:png_structrp!, method: Int32, filters: Int32)
        
        //-------------------- WHERE INTENTIONAL ERROR HAPPENS
        //---------------------------------------------------------------- IHDR
        png_set_IHDR(png_ptr, info_ptr, width, height,
                     Int32(bitDepth), colorType,
                     PNG_INTERLACE_NONE,
                     PNG_COMPRESSION_TYPE_DEFAULT,
                     PNG_FILTER_TYPE_DEFAULT
        )
        
        //------------------------------------------------------------------
        //Anything it that isn&amp;#39;t text or time has to come before IDAT, but it doesn&amp;#39;t matter the order.
        //libpng will order them correctly on output.
        
        //---------------------------------------------------------------  IDAT
        
        
        //Note, if instead we were doing the &amp;#34;long form&amp;#34; save we could change the compression
        //schemes mid image. (And this is why you use ImageMagick...)
        pixelsCopy.withUnsafeMutableBufferPointer{ pd_pointer in
            var row_pointers:[Optional&amp;lt;UnsafeMutablePointer&amp;lt;UInt8&amp;gt;&amp;gt;] = []
            for rowIndex in 0..&amp;lt;height {
                let rowStart = rowIndex * width * 4
                row_pointers.append(pd_pointer.baseAddress! + Int(rowStart))
            }
            
            //png_set_rows(png_ptr: png_const_structrp!, info_ptr: png_inforp!, row_pointers: png_bytepp!)
            png_set_rows(png_ptr, info_ptr, &amp;amp;row_pointers)
            
            //high level write.
            //TODO: Confirm theory has to be inside so row pointers still valid.
            png_write_png(png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, nil)
        }
        
        //--------------------------------------------------------   PNG CLEANUP
        png_destroy_write_struct(&amp;amp;png_ptr, &amp;amp;info_ptr);
        //---------------------------------------------------------------------
        
        return pngIOBuffer
    }
    
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Defined in SwiftLIBPNG.swift&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-Swift&#34; data-lang=&#34;Swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;writeDataCallback&lt;/span&gt;: @convention(c) (&lt;span style=&#34;color:#91d7e3&#34;&gt;Optional&lt;/span&gt;&amp;lt;OpaquePointer&amp;gt;, &lt;span style=&#34;color:#91d7e3&#34;&gt;Optional&lt;/span&gt;&amp;lt;&lt;span style=&#34;color:#91d7e3&#34;&gt;UnsafeMutablePointer&lt;/span&gt;&amp;lt;&lt;span style=&#34;color:#91d7e3&#34;&gt;UInt8&lt;/span&gt;&amp;gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;gt;&lt;/span&gt;, &lt;span style=&#34;color:#91d7e3&#34;&gt;Int&lt;/span&gt;) -&amp;gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;Void&lt;/span&gt; = { png_ptr, data_io_ptr, length &lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;guard&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;output_ptr&lt;/span&gt;:UnsafeMutableRawPointer = png_get_io_ptr(png_ptr) &lt;span style=&#34;color:#c6a0f6&#34;&gt;else&lt;/span&gt; { &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;guard&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;data_ptr&lt;/span&gt;:&lt;span style=&#34;color:#91d7e3&#34;&gt;UnsafeMutablePointer&lt;/span&gt;&amp;lt;&lt;span style=&#34;color:#91d7e3&#34;&gt;UInt8&lt;/span&gt;&amp;gt; = data_io_ptr &lt;span style=&#34;color:#c6a0f6&#34;&gt;else&lt;/span&gt; { &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//print(&amp;#34;callback io output buffer: \(output_ptr)&amp;#34;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//print(&amp;#34;callback io data buffer: \(data_ptr)&amp;#34;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;typed_output_ptr&lt;/span&gt; = output_ptr.assumingMemoryBound(to: Data.&lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        typed_output_ptr.pointee.append(data_ptr, &lt;span style=&#34;color:#91d7e3&#34;&gt;count&lt;/span&gt;: length)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description>
    </item>
    
    
    
    <item>
      <title>Uh oh, we&#39;re going Unsafe</title>
      <link>https://whynotestflight.com/excuses/uh-oh-were-going-unsafe/</link>
      <pubDate>Sat, 01 Apr 2023 00:00:00 +0000</pubDate>
      
      <guid>https://whynotestflight.com/excuses/uh-oh-were-going-unsafe/</guid>
      <description>&lt;p&gt;Now that I have a handle on writing a bit of C again, how to actually have Swift talk to it? Enter the &lt;code&gt;Unsafe&lt;/code&gt; apis.&lt;/p&gt;
&lt;p&gt;I wrote &lt;a href=&#34;https://github.com/carlynorama/UnsafeWrapCSampler&#34;&gt;https://github.com/carlynorama/UnsafeWrapCSampler&lt;/a&gt; to test it out.&lt;/p&gt;
&lt;p&gt;Like the &lt;a href=&#34;https://github.com/carlynorama/NoiseMaker&#34;&gt;NoiseMaker&lt;/a&gt; and &lt;a href=&#34;https://github.com/carlynorama/SwiftLIBPNG&#34;&gt;SwiftLIBPNG&lt;/a&gt;, the package file specifies two targets, a target for the C and one for the Swift. The Swift target uses the C target as a dependency. Unlike those two libraries (to date), I actually wrote some working Swift code!!&lt;/p&gt;
&lt;p&gt;There is a lot of code in package, so I made a companion App: &lt;a href=&#34;https://github.com/carlynorama/UnsafeExplorer&#34;&gt;UnsafeExplorer&lt;/a&gt;. I&amp;rsquo;ll write more about the UI code in that next week.&lt;/p&gt;
&lt;p&gt;This companion project never imports the C target, so it cannot call the C functions directly. It is worth noting that it can recognize (but not create) the more complex C types that are fully defined in the header even without the import. (See &lt;a href=&#34;https://github.com/carlynorama/UnsafeExplorer/blob/main/UnsafeExplorer/SubViews/RandomColorsView.swift&#34;&gt;RandomColorsView&lt;/a&gt;, testColorFunctions(), where c_color is allowed to exist as a CColorRGBA, but a new one cannot be created there. )&lt;/p&gt;
&lt;h2 id=&#34;references&#34;&gt;References&lt;/h2&gt;
&lt;p&gt;The bulk of the repo&amp;rsquo;s code was made by following along with the two WWDC videos and making examples&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://developer.apple.com/documentation/Swift/manual-memory-management&#34;&gt;https://developer.apple.com/documentation/Swift/manual-memory-management&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Unsafe Swift &lt;a href=&#34;https://developer.apple.com/videos/play/wwdc2020/10648/&#34;&gt;https://developer.apple.com/videos/play/wwdc2020/10648/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Safely manage pointers in Swift &lt;a href=&#34;https://developer.apple.com/videos/play/wwdc2020/10167/&#34;&gt;https://developer.apple.com/videos/play/wwdc2020/10167/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://developer.apple.com/documentation/swift/using-imported-c-structs-and-unions-in-swift&#34;&gt;https://developer.apple.com/documentation/swift/using-imported-c-structs-and-unions-in-swift&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://developer.apple.com/documentation/swift/opaquepointer&#34;&gt;https://developer.apple.com/documentation/swift/opaquepointer&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;using-the-unsafewrapcsample-repo&#34;&gt;Using the UnsafeWrapCSample repo&lt;/h2&gt;
&lt;p&gt;This repo is not designed to import into production code as much as to use as a reference. To quickly get a sense of what it can do, download the companion project mentioned above. It has Views for each of the major concepts.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;First scan the &lt;code&gt;random.h&lt;/code&gt; for the types of C function that the Swift examples bridge to. The header file is commented with the location of the Swift code that calls it. The C functions were written to test the Swift code, not to demonstrate best practices in C. For example, &lt;code&gt;rand()&lt;/code&gt; is not a great source for random numbers, there is very little error checking, some fairly sloppy typing (&lt;code&gt;int&lt;/code&gt; when should be &lt;code&gt;uint&lt;/code&gt; or &lt;code&gt;size_t&lt;/code&gt;, unnecessary &lt;code&gt;void*&lt;/code&gt;), lots of pointers where one wouldn&amp;rsquo;t necessarily use one, etc.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;The bulk of the code is in &lt;code&gt;RandomProvider&lt;/code&gt; which is divided into sections, each providing a different kind of random information from numbers, to arrays of numbers, to strings, to a C struct representing 32bit color information.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;BridgeColor_ColorBridge&lt;/code&gt; contains two definitions: the struct BridgeColor, the class &lt;code&gt;ColorBridge&lt;/code&gt;. These represent two different approaches for working with the OpaquePointers need to interface with C OpaqueTypes, e.g. &lt;code&gt;typedef struct COpaqueColor COpaqueColor;&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;MiscHandy&lt;/code&gt; has examples of loading in &lt;code&gt;Data&lt;/code&gt; to different types using &lt;code&gt;Unsafe&lt;/code&gt; APIs. There are also a couple of examples to get pointers into complex &lt;code&gt;Structs&lt;/code&gt;.  After the initial examples of how to fetch fixed arrays from C, there actually isn&amp;rsquo;t much that uses C. But being able to work with Data/[UInt8] formats is important for interfacing with Non-Swift APIs.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;TupleBridge&lt;/code&gt; contains some thoughts on how to deal with the fact that fixed length C arrays import into Swift as tuples by default.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;PseudoUnion&lt;/code&gt; makes no C calls at all, but is an attempt to reproduce the behavior of the C union &lt;code&gt;CColorRGBA&lt;/code&gt; using just Swift.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;`UnsafeBufferView is lifted straight from 25:52 of WWDC 2020 &amp;ldquo;Safely Manage Pointers in Swift.&amp;rdquo; (link in references)&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;lessons-learned&#34;&gt;Lessons Learned&lt;/h2&gt;
&lt;p&gt;Top take-a-ways from the exercise:&lt;/p&gt;
&lt;h3 id=&#34;use-the-closure-syntax&#34;&gt;Use the closure syntax&lt;/h3&gt;
&lt;p&gt;There is a great closure syntax for many of the APIS which means not needing to manually allocate and deallocate pointers. The closures can return any type wanted. This example uses a special Array initializer which I thought was pretty cool in and of itself. It&amp;rsquo;s a little trick because initializedCount absolutely needs to be set to tell Swift how big the array ended up being.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-Swift&#34; data-lang=&#34;Swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;makeArrayOfRandomIntClosure&lt;/span&gt;(&lt;span style=&#34;color:#91d7e3&#34;&gt;count&lt;/span&gt;:&lt;span style=&#34;color:#91d7e3&#34;&gt;Int&lt;/span&gt;) -&amp;gt; [&lt;span style=&#34;color:#91d7e3&#34;&gt;Int&lt;/span&gt;] {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//Count for this initializer is really MAX count possible, function may return an array with fewer items defined.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//both buffer and initializedCount are inout&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;tmp&lt;/span&gt; = &lt;span style=&#34;color:#91d7e3&#34;&gt;Array&lt;/span&gt;&amp;lt;&lt;span style=&#34;color:#91d7e3&#34;&gt;CInt&lt;/span&gt;&amp;gt;(unsafeUninitializedCapacity: &lt;span style=&#34;color:#91d7e3&#34;&gt;count&lt;/span&gt;) { buffer, initializedCount &lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//C:-- void random_array_of_zero_to_one_hundred(int* array, const size_t n);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            random_array_of_zero_to_one_hundred(buffer.baseAddress, &lt;span style=&#34;color:#91d7e3&#34;&gt;count&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            initializedCount = &lt;span style=&#34;color:#91d7e3&#34;&gt;count&lt;/span&gt; &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// if initializedCount is not set, Swift assumes 0, and the array returned is empty.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; tmp.&lt;span style=&#34;color:#91d7e3&#34;&gt;map&lt;/span&gt; { &lt;span style=&#34;color:#91d7e3&#34;&gt;Int&lt;/span&gt;(&lt;span style=&#34;color:#f4dbd6&#34;&gt;$0&lt;/span&gt;) }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;use-the-load-function-whenever-possible&#34;&gt;Use the .load function whenever possible.&lt;/h3&gt;
&lt;p&gt;If bytes bound to one memory type need to look like something else to the code, &lt;code&gt;.load(as:)&lt;/code&gt; is your friend.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;quadTupleToInt32&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; tuple:(&lt;span style=&#34;color:#91d7e3&#34;&gt;UInt8&lt;/span&gt;,&lt;span style=&#34;color:#91d7e3&#34;&gt;UInt8&lt;/span&gt;,&lt;span style=&#34;color:#91d7e3&#34;&gt;UInt8&lt;/span&gt;,&lt;span style=&#34;color:#91d7e3&#34;&gt;UInt8&lt;/span&gt;)) -&amp;gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;UInt32&lt;/span&gt;? {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        withUnsafeBytes(of: tuple, { bytesPointer &lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; bytesPointer.baseAddress?.load(&lt;span style=&#34;color:#c6a0f6&#34;&gt;as&lt;/span&gt;: &lt;span style=&#34;color:#91d7e3&#34;&gt;UInt32&lt;/span&gt;.&lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        })
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;There is now even a &lt;code&gt;.loadUnaligned(fromByteOffset:,as:)&lt;/code&gt; that will come in super handy for parsing data protocols in which the data may not be (aligned)[https://developer.ibm.com/articles/pa-dalign/].&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;processUnalignedData&lt;/span&gt;&amp;lt;T&amp;gt;(data:Data, &lt;span style=&#34;color:#c6a0f6&#34;&gt;as&lt;/span&gt; type:T.&lt;span style=&#34;color:#c6a0f6&#34;&gt;Type&lt;/span&gt;, offsetBy offset:&lt;span style=&#34;color:#91d7e3&#34;&gt;Int&lt;/span&gt; = &lt;span style=&#34;color:#f5a97f&#34;&gt;0&lt;/span&gt;) -&amp;gt; T {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;result&lt;/span&gt; = data.withUnsafeBytes { buffer -&amp;gt; T &lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; buffer.loadUnaligned(fromByteOffset: offset, &lt;span style=&#34;color:#c6a0f6&#34;&gt;as&lt;/span&gt;: T.&lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(result)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; result
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;use-const-in-c-function-definitions&#34;&gt;Use const in C function definitions&lt;/h3&gt;
&lt;p&gt;A &lt;code&gt;const&lt;/code&gt; in the C function definition makes a difference to the Swift &lt;code&gt;Unsafe&lt;/code&gt; pointer type. If a pointer is marked as &lt;code&gt;const&lt;/code&gt;, then Swift only requires an &lt;code&gt;UnsafePointer&lt;/code&gt;, which can be made from variables defined with &lt;code&gt;let&lt;/code&gt;. If no const in the function parameter definition, Swift will require a &lt;code&gt;var&lt;/code&gt; to create &lt;code&gt;UnsafeMutablePointer&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;To be honest, I went a little overboard and const&amp;rsquo;d the values as well. I have since confirmed that swift does NOT need that to pass in let values after all. I left them in b/c working code works. Modern C compilers are probably smart enough to write code that doesn&amp;rsquo;t copy-on pass but on change, but historically some compilers did not make a new copy of a variable for functions that promised to be safe in their declarations. I have to look into this more if I ever decide to try to compile Swift for something tiny.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://isocpp.org/wiki/faq/const-correctness#overview-const&#34;&gt;More about const and its usage (C++ discussion)&lt;/a&gt;&lt;/p&gt;
&lt;h4 id=&#34;examples&#34;&gt;Examples&lt;/h4&gt;
&lt;p&gt;&lt;code&gt;baseInt&lt;/code&gt; and &lt;code&gt;cappingAt&lt;/code&gt; don&amp;rsquo;t need to have temporary vars made for them.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;addRandom&lt;/span&gt;(to baseInt:&lt;span style=&#34;color:#91d7e3&#34;&gt;CInt&lt;/span&gt;, cappingAt:&lt;span style=&#34;color:#91d7e3&#34;&gt;CInt&lt;/span&gt; = &lt;span style=&#34;color:#91d7e3&#34;&gt;CInt&lt;/span&gt;.&lt;span style=&#34;color:#91d7e3&#34;&gt;max&lt;/span&gt;) -&amp;gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;CInt&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#91d7e3&#34;&gt;withUnsafePointer&lt;/span&gt;(to: baseInt) { (min_ptr) -&amp;gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;CInt&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#91d7e3&#34;&gt;withUnsafePointer&lt;/span&gt;(to: cappingAt) { (max_ptr) -&amp;gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;CInt&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//C:-- int random_number_in_range(const int* min, const int* max);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; random_number_in_range(min_ptr, max_ptr);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;baseArray&lt;/code&gt; does need a copy made since it is not passed in as an &lt;code&gt;inout&lt;/code&gt; variable. Strictly speaking this is safer, but depending on the buffer size may not be the desired behavior. Note the super swank temporary implicit &lt;code&gt;UnsafeMutableBufferPointer&lt;/code&gt; created. So so nice.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   &lt;span style=&#34;color:#ed8796&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;addRandomWithCap&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; baseArray:[&lt;span style=&#34;color:#91d7e3&#34;&gt;UInt32&lt;/span&gt;], newValueCap:&lt;span style=&#34;color:#91d7e3&#34;&gt;UInt32&lt;/span&gt;) -&amp;gt; [&lt;span style=&#34;color:#91d7e3&#34;&gt;UInt32&lt;/span&gt;] {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;arrayCopy&lt;/span&gt; = baseArray
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//C:-- void add_random_to_all_capped(unsigned int* array, const size_t n, unsigned int cap);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        add_random_to_all_capped(&amp;amp;arrayCopy, arrayCopy.&lt;span style=&#34;color:#91d7e3&#34;&gt;count&lt;/span&gt;, newValueCap)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; arrayCopy
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;dont-for-get-about-byte-direction&#34;&gt;Don&amp;rsquo;t for get about byte direction&lt;/h3&gt;
&lt;p&gt;Mac OS and many other systems are little endian, but &amp;ldquo;The Network&amp;rdquo; and many protocols are not. A well written API will not rely on the endianness of the system, but not all APIs are well written.&lt;/p&gt;
&lt;p&gt;For example, in my code I wrote a union that would let me enter #RRGGBBAA to encode color information into a UINT32. It is NOT actually compliant with the OpenGL and PNG format RGBA32, because that data specification assumes the numbers are encoded
with RED at byte[0], not byte[4]. Little endian systems will load the UInt32  #FFCC9966 into memory as [66, 99, CC, FF] instead.&lt;/p&gt;
&lt;p&gt;Little Endian systems should implement #AABBGGRR style numbers but that is the opposite of how I&amp;rsquo;m used to writing hex colors, so I did not for this code.&lt;/p&gt;
&lt;p&gt;To check a given system, try one of the following:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;lscpu | grep Endian&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;echo -n I | od -to2 | awk &#39;FNR==1{ print substr($2,6,1)}&#39;&lt;/code&gt;  (return will be 1 for little endian, 0 for big)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;python3 -c &amp;quot;import sys;print(sys.byteorder)&amp;quot;&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;swift-unsafe-api-names&#34;&gt;Swift Unsafe API names&lt;/h2&gt;
&lt;h3 id=&#34;typed-pointers&#34;&gt;Typed Pointers&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&#34;https://developer.apple.com/documentation/swift/unsafepointer&#34;&gt;&lt;code&gt;UnsafePointer&lt;/code&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&#34;https://developer.apple.com/documentation/swift/unsafemutablepointer&#34;&gt;&lt;code&gt;UnsafeMutablePointer&lt;/code&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&#34;https://developer.apple.com/documentation/swift/unsafebufferpointer&#34;&gt;&lt;code&gt;UnsafeBufferPointer&amp;lt;Element&amp;gt;&lt;/code&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&#34;https://developer.apple.com/documentation/swift/unsafemutablepointer&#34;&gt;&lt;code&gt;UnsafeMutableBufferPointer&amp;lt;Element&amp;gt;&lt;/code&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;raw-pointers&#34;&gt;Raw Pointers&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;[Unmanaged]&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&#34;https://developer.apple.com/documentation/swift/unsaferawpointer&#34;&gt;&lt;code&gt;UnsafeRawPointer&lt;/code&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&#34;https://developer.apple.com/documentation/swift/unsafemutablerawpointer&#34;&gt;&lt;code&gt;UnsafeMutableRawPointer&lt;/code&gt;&lt;/a&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://developer.apple.com/documentation/swift/unsafemutablerawpointer/storebytes(of:tobyteoffset:as:)&#34;&gt;https://developer.apple.com/documentation/swift/unsafemutablerawpointer/storebytes(of:tobyteoffset:as:)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;The type T to be stored must be a trivial type. The memory must also be uninitialized, initialized to T, or initialized to another trivial type that is layout compatible with T.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&#34;https://developer.apple.com/documentation/swift/unsaferawbufferpointer&#34;&gt;&lt;code&gt;UnsafeRawBufferPointer&lt;/code&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&#34;https://developer.apple.com/documentation/swift/unsafemutablerawbufferpointer&#34;&gt;&lt;code&gt;UnsafeMutableRawBufferPointer&lt;/code&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&#34;https://developer.apple.com/documentation/swift/array/withcontiguousstorageifavailable(_:)-1wj7c&#34;&gt;&lt;code&gt;Sequence.withContiguousStorageIfAvailable(_:)&lt;/code&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&#34;https://developer.apple.com/documentation/swift/slice/withcontiguousmutablestorageifavailable(_:)-2ader&#34;&gt;&lt;code&gt;MutableCollection.withContiguousMutableStorageIfAvailable(_:)&lt;/code&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;misc-other-functions&#34;&gt;Misc other functions&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;[&lt;code&gt;String.withCString(_:)&lt;/code&gt;](&lt;a href=&#34;https://developer.apple.com/documentation/swift/string/withcstring(_:)&#34;&gt;https://developer.apple.com/documentation/swift/string/withcstring(_:)&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&#34;https://developer.apple.com/documentation/swift/string/utf8cstring&#34;&gt;&lt;code&gt;String.withUTF8(_:)&lt;/code&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&#34;https://developer.apple.com/documentation/swift/array/withunsafebytes(_:)&#34;&gt;&lt;code&gt;Array.withUnsafeBytes(_:)&lt;/code&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&#34;https://developer.apple.com/documentation/swift/array/withunsafebufferpointer(_:)&#34;&gt;&lt;code&gt;Array.withUnsafeBufferPointer(_:)&lt;/code&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&#34;https://developer.apple.com/documentation/swift/array/withunsafemutablebytes(_:)&#34;&gt;&lt;code&gt;Array.withUnsafeMutableBytes(_:)&lt;/code&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&#34;https://developer.apple.com/documentation/swift/array/withunsafemutablebufferpointer(_:)&#34;&gt;&lt;code&gt;Array.withUnsafeMutableBufferPointer(_:)&lt;/code&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&#34;https://developer.apple.com/documentation/swift/withunsafepointer(to:_:)-1wfum&#34;&gt;&lt;code&gt;withUnsafePointer(to:_:)&lt;/code&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&#34;https://developer.apple.com/documentation/swift/withunsafemutablepointer(to:_:)&#34;&gt;&lt;code&gt;withUnsafeMutablePointer(to:_:)&lt;/code&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&#34;https://developer.apple.com/documentation/swift/withunsafebytes(of:_:)-9p5df&#34;&gt;&lt;code&gt;withUnsafeBytes(of:_:)&lt;/code&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&#34;https://developer.apple.com/documentation/swift/withunsafemutablebytes(of:_:)&#34;&gt;&lt;code&gt;withUnsafeMutableBytes(of:_:)&lt;/code&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;try-to-avoid&#34;&gt;Try to Avoid&lt;/h3&gt;
&lt;p&gt;These rebind memory types. Better to do non-rebinding casting withUnsafeBytes or rawPointer.load(as)
Since working with C anyway, pass the pointer into a &lt;code&gt;void*&lt;/code&gt; and do what you need to do. YOLO.&lt;/p&gt;
&lt;p&gt;(See UnsafeBufferView for the better way.)&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://developer.apple.com/documentation/swift/unsafemutablerawpointer/assumingmemorybound(to:)&#34;&gt;assumingMemoryBound(to:)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://developer.apple.com/documentation/swift/unsafemutablerawpointer/bindmemory(to:capacity:)&#34;&gt;bindMemory(to:capacity)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://developer.apple.com/documentation/swift/unsafemutablerawpointer/withmemoryrebound(to:capacity:_:)&#34;&gt;withMemoryRebound(to:capacity:)&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;todo&#34;&gt;TODO:&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;//init(bitPattern pointer: OpaquePointer?)&lt;/li&gt;
&lt;li&gt;//init(bitPattern objectID: ObjectIdentifier)&lt;/li&gt;
&lt;/ul&gt;
</description>
    </item>
    
    
    
    <item>
      <title>So what if I wanted to write some C with NO Swift?</title>
      <link>https://whynotestflight.com/excuses/so-what-if-i-wanted-to-write-some-c-with-no-swift/</link>
      <pubDate>Sat, 25 Mar 2023 00:00:00 +0000</pubDate>
      
      <guid>https://whynotestflight.com/excuses/so-what-if-i-wanted-to-write-some-c-with-no-swift/</guid>
      <description>&lt;p&gt;It&amp;rsquo;s been awhile since I wrote much C, and I certainly don&amp;rsquo;t have a solid VScode workflow for it.&lt;/p&gt;
&lt;p&gt;I made a sample multi-file C project and I love that it&amp;rsquo;s 61.4% makefile and 38.6% C&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://github.com/carlynorama/Hello_C_using_VScode&#34;&gt;https://github.com/carlynorama/Hello_C_using_VScode&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&#34;references&#34;&gt;References&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;About VSCode &amp;amp; C/C++
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://code.visualstudio.com/docs/cpp/config-clang-mac&#34;&gt;https://code.visualstudio.com/docs/cpp/config-clang-mac&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Visual Studio Code for C/C++ on Linux (2021) &lt;a href=&#34;https://www.youtube.com/watch?v=9pjBseGfEPU&#34;&gt;https://www.youtube.com/watch?v=9pjBseGfEPU&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://stackoverflow.com/questions/52770066/debugging-c-using-visual-studio-code-on-windows&#34;&gt;https://stackoverflow.com/questions/52770066/debugging-c-using-visual-studio-code-on-windows&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://code.visualstudio.com/docs/editor/variables-reference&#34;&gt;https://code.visualstudio.com/docs/editor/variables-reference&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://code.visualstudio.com/Docs/editor/tasks&#34;&gt;https://code.visualstudio.com/Docs/editor/tasks&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://code.visualstudio.com/docs/editor/tasks#_custom-tasks&#34;&gt;https://code.visualstudio.com/docs/editor/tasks#_custom-tasks&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://code.visualstudio.com/docs/editor/tasks-appendix&#34;&gt;https://code.visualstudio.com/docs/editor/tasks-appendix&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://code.visualstudio.com/docs/cpp/config-mingw&#34;&gt;https://code.visualstudio.com/docs/cpp/config-mingw&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;About makefiles:
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://bytes.usc.edu/cs104/wiki/makefile/&#34;&gt;https://bytes.usc.edu/cs104/wiki/makefile/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://cs.colby.edu/maxwell/courses/tutorials/maketutor/&#34;&gt;https://cs.colby.edu/maxwell/courses/tutorials/maketutor/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;make -p&lt;/code&gt; to see all the pre defined vars and implicit rules that make makefiles magic (&amp;hellip;and hard to follow)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;steps-taken&#34;&gt;Steps taken&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;(VSCode, XCode command line tools already installed.)&lt;/li&gt;
&lt;li&gt;Installed Microsoft C/C++ extension&lt;/li&gt;
&lt;li&gt;made a folder, opened it&lt;/li&gt;
&lt;li&gt;added a &lt;code&gt;.gitignore&lt;/code&gt; (see below)&lt;/li&gt;
&lt;li&gt;made &lt;code&gt;hello_world.c&lt;/code&gt; (see below)&lt;/li&gt;
&lt;li&gt;hit the debug button and selected C tool (clang, e.g.)
&lt;ul&gt;
&lt;li&gt;look at &lt;code&gt;tasks.json&lt;/code&gt; file created&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Saw output in debug window! That was easy! Nice!&lt;/li&gt;
&lt;li&gt;try adding &lt;code&gt;second_file.c&lt;/code&gt; and &lt;code&gt;second_file.h&lt;/code&gt;
&amp;hellip;. CLONK&amp;hellip;&lt;/li&gt;
&lt;/ol&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;Undefined symbols for architecture arm64:
  &amp;#34;_and_so_we_meet_again&amp;#34;, referenced from:
      _main in hello_world-5211a2.o
ld: symbol(s) not found for architecture arm64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
&lt;/code&gt;&lt;/pre&gt;&lt;ol start=&#34;8&#34;&gt;
&lt;li&gt;manual compile check&lt;/li&gt;
&lt;/ol&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;clang hello_world.c second_file.c
./a.out
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&amp;hellip; worked fine. Do I need to add a make file?&lt;/p&gt;
&lt;ol start=&#34;9&#34;&gt;
&lt;li&gt;
&lt;p&gt;Yes. I need to do one of two things&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A) in tasks.json change &lt;code&gt;&amp;quot;{$file}&amp;quot;,&lt;/code&gt; to &lt;code&gt;&amp;quot;hello_world.c&amp;quot;, &amp;quot;second_file.c&amp;quot;,&lt;/code&gt; which I did and it works just fine.&lt;/li&gt;
&lt;li&gt;B) OR add a make file. (later)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;F5 to start the process of making a launch.json? Sure. See video.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;make some small edits to launch.json, especially &lt;code&gt;&amp;quot;preLaunchTask&amp;quot;: &amp;quot;C/C++: clang build active file&amp;quot;&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&amp;mdash; (Later)&lt;/p&gt;
&lt;ol start=&#34;12&#34;&gt;
&lt;li&gt;
&lt;p&gt;create a test makefile (see &lt;code&gt;makefiles_for_testing/test&lt;/code&gt;), run &lt;code&gt;make&lt;/code&gt; and &lt;code&gt;make clean&lt;/code&gt; to confirm make is installed and working.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Get a real Makefile working&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Add a task to tasks.json, add it launch.json&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;TODO: figure out adding CMake. &lt;a href=&#34;https://code.visualstudio.com/docs/cpp/cmake-linux&#34;&gt;https://code.visualstudio.com/docs/cpp/cmake-linux&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&#34;files&#34;&gt;Files&lt;/h2&gt;
&lt;h3 id=&#34;hello_worldc&#34;&gt;hello_world.c&lt;/h3&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#include&lt;/span&gt; &lt;span style=&#34;color:#6e738d;font-weight:bold;font-style:italic&#34;&gt;&amp;lt;stdio.h&amp;gt;&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#include&lt;/span&gt; &lt;span style=&#34;color:#6e738d;font-weight:bold;font-style:italic&#34;&gt;&amp;#34;second_file.h&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;int&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;main&lt;/span&gt;(&lt;span style=&#34;color:#ed8796&#34;&gt;int&lt;/span&gt; argc, &lt;span style=&#34;color:#ed8796&#34;&gt;char&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;*&lt;/span&gt;argv[]) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#8aadf4&#34;&gt;printf&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Hello World.&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#8aadf4&#34;&gt;and_so_we_meet_again&lt;/span&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;second_filec&#34;&gt;second_file.c&lt;/h3&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#include&lt;/span&gt; &lt;span style=&#34;color:#6e738d;font-weight:bold;font-style:italic&#34;&gt;&amp;lt;stdio.h&amp;gt;&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#include&lt;/span&gt; &lt;span style=&#34;color:#6e738d;font-weight:bold;font-style:italic&#34;&gt;&amp;#34;second_file.h&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;void&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;and_so_we_meet_again&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#8aadf4&#34;&gt;printf&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;... and so we meet ...again?&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;second_fileh&#34;&gt;second_file.h&lt;/h3&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#pragma once
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;void&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;and_so_we_meet_again&lt;/span&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;final-makefile&#34;&gt;final Makefile&lt;/h3&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-makefile&#34; data-lang=&#34;makefile&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;CC&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt;clang
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;CFLAGS&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt;-c -Wall
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;LDFLAGS&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;SOURCES&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt;hello_world.c second_file.c
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;OBJDIR&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt;obj
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;_OBJECTS&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;$(&lt;/span&gt;SOURCES:.c&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt;.o&lt;span style=&#34;color:#c6a0f6&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;OBJECTS&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;$(&lt;/span&gt;patsubst %,&lt;span style=&#34;color:#c6a0f6&#34;&gt;$(&lt;/span&gt;OBJDIR&lt;span style=&#34;color:#c6a0f6&#34;&gt;)&lt;/span&gt;/%,&lt;span style=&#34;color:#c6a0f6&#34;&gt;$(&lt;/span&gt;_OBJECTS&lt;span style=&#34;color:#c6a0f6&#34;&gt;))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;EXECUTABLE&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt;hello_world
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;DEST_DIR&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt;bin
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;all&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;$(&lt;/span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;SOURCES&lt;/span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;)&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;$(&lt;/span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;EXECUTABLE&lt;/span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;$(EXECUTABLE)&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;$(&lt;/span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;OBJECTS&lt;/span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	&lt;span style=&#34;color:#c6a0f6&#34;&gt;$(&lt;/span&gt;CC&lt;span style=&#34;color:#c6a0f6&#34;&gt;)&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;$(&lt;/span&gt;LDFLAGS&lt;span style=&#34;color:#c6a0f6&#34;&gt;)&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;$(&lt;/span&gt;OBJECTS&lt;span style=&#34;color:#c6a0f6&#34;&gt;)&lt;/span&gt; -o &lt;span style=&#34;color:#c6a0f6&#34;&gt;$(&lt;/span&gt;DEST_DIR&lt;span style=&#34;color:#c6a0f6&#34;&gt;)&lt;/span&gt;/&lt;span style=&#34;color:#f4dbd6&#34;&gt;$@&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;$(OBJDIR)/%.o&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;:&lt;/span&gt; %.c
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	&lt;span style=&#34;color:#c6a0f6&#34;&gt;$(&lt;/span&gt;CC&lt;span style=&#34;color:#c6a0f6&#34;&gt;)&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;$(&lt;/span&gt;CFLAGS&lt;span style=&#34;color:#c6a0f6&#34;&gt;)&lt;/span&gt; $&amp;lt; -o &lt;span style=&#34;color:#f4dbd6&#34;&gt;$@&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# `make clean` removes contents of bin folder and any random .o files
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;clean&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	rm -rf &lt;span style=&#34;color:#c6a0f6&#34;&gt;$(&lt;/span&gt;OBJDIR&lt;span style=&#34;color:#c6a0f6&#34;&gt;)&lt;/span&gt;/*.o
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	rm -rf &lt;span style=&#34;color:#c6a0f6&#34;&gt;$(&lt;/span&gt;DEST_DIR&lt;span style=&#34;color:#c6a0f6&#34;&gt;)&lt;/span&gt;/&lt;span style=&#34;color:#c6a0f6&#34;&gt;$(&lt;/span&gt;EXECUTABLE&lt;span style=&#34;color:#c6a0f6&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;gitignore&#34;&gt;.gitignore&lt;/h3&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-git&#34; data-lang=&#34;git&#34;&gt;.DS_Store

#name of compiled program
hello_world

/*.dSYM
*.out
/bin
/obj

# in this example, go ahead and show the .vscode folder
#/.vscode


# C/C++ Files object files 
*.o 
*.a 
*.so
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&#34;vscode-helper-files&#34;&gt;VSCode Helper files&lt;/h2&gt;
&lt;h3 id=&#34;tasksjson&#34;&gt;tasks.json&lt;/h3&gt;
&lt;p&gt;Created when I hit the debug button for the first time.&lt;/p&gt;
&lt;p&gt;The first task, &lt;code&gt;cppbuild&lt;/code&gt;, is no longer being used by me, but I&amp;rsquo;ve left it in for the record.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-json&#34; data-lang=&#34;json&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;&amp;#34;tasks&amp;#34;&lt;/span&gt;: [
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;&amp;#34;type&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;cppbuild&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;&amp;#34;label&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;C/C++: clang build active file&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;&amp;#34;command&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;/usr/bin/clang&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;&amp;#34;args&amp;#34;&lt;/span&gt;: [
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;-fcolor-diagnostics&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;-fansi-escape-codes&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;-g&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;hello_world.c&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;second_file.c&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;-o&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;${fileDirname}/bin/${fileBasenameNoExtension}&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            ],
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;&amp;#34;options&amp;#34;&lt;/span&gt;: {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#c6a0f6&#34;&gt;&amp;#34;cwd&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;${fileDirname}&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            },
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;&amp;#34;problemMatcher&amp;#34;&lt;/span&gt;: [
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;$gcc&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            ],
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;&amp;#34;group&amp;#34;&lt;/span&gt;: {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#c6a0f6&#34;&gt;&amp;#34;kind&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;build&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#c6a0f6&#34;&gt;&amp;#34;isDefault&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#f5a97f&#34;&gt;false&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            },
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;&amp;#34;detail&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Task generated by Debugger.&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        },
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;&amp;#34;type&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;process&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//should this be done as shell or process? right now no args
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;&amp;#34;label&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Build using make&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;&amp;#34;command&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;make&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;&amp;#34;options&amp;#34;&lt;/span&gt;: {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#c6a0f6&#34;&gt;&amp;#34;cwd&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;${workspaceFolder}&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            },
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;&amp;#34;group&amp;#34;&lt;/span&gt;: {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#c6a0f6&#34;&gt;&amp;#34;kind&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;build&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#c6a0f6&#34;&gt;&amp;#34;isDefault&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#f5a97f&#34;&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            },
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;&amp;#34;problemMatcher&amp;#34;&lt;/span&gt;: [
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;$gcc&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            ],
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;&amp;#34;detail&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;What does adding a detail do?&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        },
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    ],
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;&amp;#34;version&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;2.0.0&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;launchjson&#34;&gt;launch.json&lt;/h3&gt;
&lt;p&gt;This is the file that triggers building the makefile task via &lt;code&gt;&amp;quot;preLaunchTask&amp;quot;: &amp;quot;Build using make&amp;quot;&lt;/code&gt;&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-json&#34; data-lang=&#34;json&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;&amp;#34;version&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;0.2.0&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;&amp;#34;configurations&amp;#34;&lt;/span&gt;: [
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;&amp;#34;name&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;(lldb) Launch&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;&amp;#34;type&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;cppdbg&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;&amp;#34;request&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;launch&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//change this line to match tasks.json
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;&amp;#34;program&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;${workspaceFolder}/bin/hello_world&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;&amp;#34;args&amp;#34;&lt;/span&gt;: [],
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;&amp;#34;stopAtEntry&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#f5a97f&#34;&gt;false&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;&amp;#34;cwd&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;${fileDirname}&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;&amp;#34;environment&amp;#34;&lt;/span&gt;: [],
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//TBD on which I prefer.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;            &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//&amp;#34;externalConsole&amp;#34;: true,
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;&amp;#34;externalConsole&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#f5a97f&#34;&gt;false&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;&amp;#34;MIMode&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;lldb&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//added to compile before launch
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;            &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//also needs to match tasks.json
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;&amp;#34;preLaunchTask&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Build using make&amp;#34;&lt;/span&gt;,    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    ]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;make-files-for-testing&#34;&gt;Make Files for testing&lt;/h2&gt;
&lt;h3 id=&#34;hello-make&#34;&gt;hello make&lt;/h3&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-makefile&#34; data-lang=&#34;makefile&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;all&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;:&lt;/span&gt; one two three
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;one&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	&lt;span style=&#34;color:#91d7e3&#34;&gt;echo&lt;/span&gt; “create file one”
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	touch one
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;two&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	&lt;span style=&#34;color:#91d7e3&#34;&gt;echo&lt;/span&gt; “create file two”
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	touch two
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;three&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	&lt;span style=&#34;color:#91d7e3&#34;&gt;echo&lt;/span&gt; “create file three”
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	touch three
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;clean&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	&lt;span style=&#34;color:#91d7e3&#34;&gt;echo&lt;/span&gt; “clean up files”
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	rm -f one two three
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;super-basic&#34;&gt;super basic&lt;/h3&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-makefile&#34; data-lang=&#34;makefile&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# Always compiles everything.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#none of the calls are file names, so lets keep make from getting confused.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;.PHONY&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;:&lt;/span&gt; clean simple verbose
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# `make` or `make simple` will compile the files into output file after -o
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;simple&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;:&lt;/span&gt; hello_world.c second_file.c
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	clang hello_world.c second_file.c -o bin/hello_world
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# `make verbose` will compile the files with -g (debugging information) and -Wall (compiler warnings)	
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;verbose&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;:&lt;/span&gt; hello_world.c second_file.c
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	clang -g -Wall hello_world.c second_file.c  -o bin/hello_world
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# `make clean` removes contents of bin folder, there isn&amp;#39;t a &amp;#34;clean&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;clean&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	rm -rf bin/*
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;explicit-two-file-set-up&#34;&gt;explicit two file set up&lt;/h3&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-makefile&#34; data-lang=&#34;makefile&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;all&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;:&lt;/span&gt; hello_world
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# compiles main program
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;hello_world&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;:&lt;/span&gt; hello_world.c second_file.o
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	clang -g -Wall hello_world.c bin/second_file.o -o bin/hello_world
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# will compile second file if needed
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;second_file.o&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;:&lt;/span&gt; second_file.c second_file.h
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	clang -g -Wall -c second_file.c -o bin/second_file.o
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# `make clean` removes contents of bin folder
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# run even if there is a file called clean
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;.PHONY&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;:&lt;/span&gt; clean
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;clean&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	rm -rf bin/*
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;start-adding-variables&#34;&gt;Start adding variables&lt;/h3&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-makefile&#34; data-lang=&#34;makefile&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;CC&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt;clang
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;CFLAGS&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt;-c -Wall
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;LDFLAGS&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;SOURCES&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt;hello_world.c second_file.c
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;OBJECTS&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;$(&lt;/span&gt;SOURCES:.c&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt;.o&lt;span style=&#34;color:#c6a0f6&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;EXECUTABLE&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt;hello
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;all&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;$(&lt;/span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;SOURCES&lt;/span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;)&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;$(&lt;/span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;EXECUTABLE&lt;/span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;$(EXECUTABLE)&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;$(&lt;/span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;OBJECTS&lt;/span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	&lt;span style=&#34;color:#c6a0f6&#34;&gt;$(&lt;/span&gt;CC&lt;span style=&#34;color:#c6a0f6&#34;&gt;)&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;$(&lt;/span&gt;LDFLAGS&lt;span style=&#34;color:#c6a0f6&#34;&gt;)&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;$(&lt;/span&gt;OBJECTS&lt;span style=&#34;color:#c6a0f6&#34;&gt;)&lt;/span&gt; -o &lt;span style=&#34;color:#f4dbd6&#34;&gt;$@&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;.c.o&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	&lt;span style=&#34;color:#c6a0f6&#34;&gt;$(&lt;/span&gt;CC&lt;span style=&#34;color:#c6a0f6&#34;&gt;)&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;$(&lt;/span&gt;CFLAGS&lt;span style=&#34;color:#c6a0f6&#34;&gt;)&lt;/span&gt; $&amp;lt; -o &lt;span style=&#34;color:#f4dbd6&#34;&gt;$@&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# `make clean` removes .o files and compiled program
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# run even if there is a file called clean
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;.PHONY&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;:&lt;/span&gt; clean
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;clean&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	rm -f *.o &lt;span style=&#34;color:#c6a0f6&#34;&gt;$(&lt;/span&gt;EXECUTABLE&lt;span style=&#34;color:#c6a0f6&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;put-built-files-in-sub-folders&#34;&gt;Put built files in sub folders&lt;/h3&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-makefile&#34; data-lang=&#34;makefile&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;CC&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt;clang
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;CFLAGS&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt;-c -Wall
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;LDFLAGS&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;SOURCES&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt;hello_world.c second_file.c
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;OBJDIR&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt;obj
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;_OBJECTS&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;$(&lt;/span&gt;SOURCES:.c&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt;.o&lt;span style=&#34;color:#c6a0f6&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;OBJECTS&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;$(&lt;/span&gt;patsubst %,&lt;span style=&#34;color:#c6a0f6&#34;&gt;$(&lt;/span&gt;OBJDIR&lt;span style=&#34;color:#c6a0f6&#34;&gt;)&lt;/span&gt;/%,&lt;span style=&#34;color:#c6a0f6&#34;&gt;$(&lt;/span&gt;_OBJECTS&lt;span style=&#34;color:#c6a0f6&#34;&gt;))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;EXECUTABLE&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt;hello
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;DEST_DIR&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;=&lt;/span&gt;bin
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;all&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;$(&lt;/span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;SOURCES&lt;/span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;)&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;$(&lt;/span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;EXECUTABLE&lt;/span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;$(EXECUTABLE)&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;$(&lt;/span&gt;&lt;span style=&#34;color:#f4dbd6&#34;&gt;OBJECTS&lt;/span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	&lt;span style=&#34;color:#c6a0f6&#34;&gt;$(&lt;/span&gt;CC&lt;span style=&#34;color:#c6a0f6&#34;&gt;)&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;$(&lt;/span&gt;LDFLAGS&lt;span style=&#34;color:#c6a0f6&#34;&gt;)&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;$(&lt;/span&gt;OBJECTS&lt;span style=&#34;color:#c6a0f6&#34;&gt;)&lt;/span&gt; -o &lt;span style=&#34;color:#c6a0f6&#34;&gt;$(&lt;/span&gt;DEST_DIR&lt;span style=&#34;color:#c6a0f6&#34;&gt;)&lt;/span&gt;/&lt;span style=&#34;color:#f4dbd6&#34;&gt;$@&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;$(OBJDIR)/%.o&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;:&lt;/span&gt; %.c
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	&lt;span style=&#34;color:#c6a0f6&#34;&gt;$(&lt;/span&gt;CC&lt;span style=&#34;color:#c6a0f6&#34;&gt;)&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;$(&lt;/span&gt;CFLAGS&lt;span style=&#34;color:#c6a0f6&#34;&gt;)&lt;/span&gt; $&amp;lt; -o &lt;span style=&#34;color:#f4dbd6&#34;&gt;$@&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# `make clean` removes contents of bin folder and any random .o files
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# run even if there is a file called clean
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;.PHONY&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;:&lt;/span&gt; clean
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;clean&lt;/span&gt;&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	rm -rf *.o
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	rm -rf &lt;span style=&#34;color:#c6a0f6&#34;&gt;$(&lt;/span&gt;DEST_DIR&lt;span style=&#34;color:#c6a0f6&#34;&gt;)&lt;/span&gt;/*
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description>
    </item>
    
    
    
    <item>
      <title>Can I get my hands on a homebrew installed library?</title>
      <link>https://whynotestflight.com/excuses/can-i-get-my-hands-on-a-homebrew-installed-library/</link>
      <pubDate>Sat, 18 Mar 2023 00:00:00 +0000</pubDate>
      
      <guid>https://whynotestflight.com/excuses/can-i-get-my-hands-on-a-homebrew-installed-library/</guid>
      <description>&lt;p&gt;Once the pixel data is generated (&lt;a href=&#34;https://whynotestflight.com/excuses/but-some-of-my-best-friends-are-c/&#34;&gt;okay, which it isn&amp;rsquo;t yet&lt;/a&gt;), that data will need to be saved to a file that can be shared on the internet.&lt;/p&gt;
&lt;p&gt;The &lt;a href=&#34;http://www.libpng.org/pub/png/&#34;&gt;PNG file format spec&lt;/a&gt; is pretty straight forward, and there is an official library for it called &lt;code&gt;libpng&lt;/code&gt;.  &lt;code&gt;ImageMagick&lt;/code&gt; and &lt;code&gt;ffmpeg&lt;/code&gt; depend on &lt;code&gt;libpng&lt;/code&gt; and I typically have those installed.&lt;/p&gt;
&lt;p&gt;This week I investigated if I could in fact wrap a system library in a package and then use it from Swift. I got to &amp;ldquo;Hello version&amp;rdquo; pretty fast, but then realized my C was pretty rusty!&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://github.com/carlynorama/SwiftLIBPNG&#34;&gt;https://github.com/carlynorama/SwiftLIBPNG&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&#34;references&#34;&gt;References&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/apple/swift/blob/main/docs/HowSwiftImportsCAPIs.md&#34;&gt;How Swift imports C APIs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://theswiftdev.com/how-to-use-c-libraries-in-swift/&#34;&gt;How to use C libraries in Swift?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://www.hackingwithswift.com/articles/87/how-to-wrap-a-c-library-in-swift&#34;&gt;How to wrap a C library in Swift&lt;/a&gt;, but also its more &lt;a href=&#34;https://github.com/twostraws/SwiftGD&#34;&gt;up to date repo&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://rderik.com/blog/making-a-c-library-available-in-swift-using-the-swift-package/&#34;&gt;Making a C library available in Swift using the Swift Package Manager&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://clang.llvm.org/docs/Modules.html&#34;&gt;https://clang.llvm.org/docs/Modules.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://rlaguilar.com/posts/integrate-c-library-ios-project-swift/&#34;&gt;Guide to including a C library into an iOS project written in Swift&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;(https://github.com/apple/swift-evolution/blob/main/proposals/0238-package-manager-build-settings.md)&#34;&gt;PackageManager BuildSettings Proposal&lt;/a&gt; (implemented)&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://developer.apple.com/documentation/packagedescription/linkersetting&#34;&gt;PackageManager LinkerSettings&lt;/a&gt; for when it really is a System library.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;checking-for-packages&#34;&gt;Checking for Packages&lt;/h2&gt;
&lt;p&gt;Install checks using &lt;code&gt;homebrew&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-zsh&#34; data-lang=&#34;zsh&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# Check if installed at all&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;which libpng
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# Check if installed&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;brew ls --versions libpng
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# Install it if necessary&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;brew install libpng
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# Check who uses it&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;brew uses --installed libpng
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# Check what it needs, including dependencies of dependencies&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# which in the case of libpng is nothing.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;brew deps --include-build libpng
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# just get more info&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;brew info libpng
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Install checks using &lt;code&gt;apt&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-zsh&#34; data-lang=&#34;zsh&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# Check if installed at all&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;which libpng
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# Check if installed&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;apt list --installed libpng-dev
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# Install it if necessary&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;sudo apt-get install libpng-dev
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# Check who uses it&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;apt-cache rdepends libpng-dev
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# Check what it needs&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# which in the case of libpng is nothing.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;sudo apt depends libpng-dev
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# just get more info&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;apt-cache show libpng-dev
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;making-the-package&#34;&gt;Making the Package&lt;/h2&gt;
&lt;p&gt;Here are the general steps to wrap a system library in a Package with some helper Swift code. Like last week I have an example package that is a WIP.&lt;/p&gt;
&lt;h3 id=&#34;learn-about-the-library-you-want-to-wrap&#34;&gt;Learn about the library you want to wrap.&lt;/h3&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-zsh&#34; data-lang=&#34;zsh&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;brew install &lt;span style=&#34;color:#f4dbd6&#34;&gt;$THING_TO_WRAP&lt;/span&gt;  
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#91d7e3&#34;&gt;cd&lt;/span&gt; /usr/local/include/
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ls -a 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# look for header file of $THING_TO_WRAP so you know its name for later. &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;start-the-library&#34;&gt;Start the Library&lt;/h3&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-zsh&#34; data-lang=&#34;zsh&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;mkdir &lt;span style=&#34;color:#f4dbd6&#34;&gt;$YOUR_LIBRARY_NAME&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#91d7e3&#34;&gt;cd&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;$YOUR_LIBRARY_NAME&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# Note HWS tutorial uses `system-module` which appears to be deprecated. &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;swift package init --type library 
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h4 id=&#34;update-packageswift-targets-section-to-include-a-reference-to-the-installed-c-system-library&#34;&gt;Update Package.swift target&amp;rsquo;s section to include a reference to the installed C system library&lt;/h4&gt;
&lt;p&gt;(see contents of full file below)&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://developer.apple.com/documentation/packagedescription/target/systemlibrary(name:path:pkgconfig:providers:)&#34;&gt;https://developer.apple.com/documentation/packagedescription/target/systemlibrary(name:path:pkgconfig:providers:)&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;In this example the &lt;code&gt;name&lt;/code&gt; is the same as the folder where modulemap lives, which the same as the libraries header file (without the .h)), which is the same as the module map link. This kept it easiest for me.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;pkgConfig&lt;/code&gt; parameter is an &lt;a href=&#34;https://developer.apple.com/documentation/packagedescription/target/systemlibrary(name:path:pkgconfig:providers:)&#34;&gt;optional&lt;/a&gt; setting, but it does appear to be required for libraries not really in the the System or in the CommandLineTools SDK. The name needed can be found by (on a computer with pkg-config installed) with &lt;code&gt;pkg-config --list-all | grep $THING_TO_WRAP&lt;/code&gt; or some fraction of the &lt;code&gt;$THING_TO_WRAP&lt;/code&gt; name. I was not able to get this package to compile without &lt;code&gt;pkg-config&lt;/code&gt; installed and without this parameter set. My guess is that is because &lt;code&gt;libpng&lt;/code&gt; is not a real System Library, nor in the CommandLineTools SDK.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;providers&lt;/code&gt; is truly optional adding &lt;code&gt;providers&lt;/code&gt; will NOT auto install dependencies at this time (2023 Apr).&lt;/p&gt;
&lt;p&gt;Neither &lt;code&gt;pkgConfig&lt;/code&gt; or &lt;code&gt;providers&lt;/code&gt; will auto install dependencies, is my current understanding.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;.systemLibrary(name: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;png&amp;#34;&lt;/span&gt;, pkgConfig: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;libpng&amp;#34;&lt;/span&gt;, providers: [.apt([&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;libpng-dev&amp;#34;&lt;/span&gt;]), .brew([&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;libpng&amp;#34;&lt;/span&gt;])]),
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Make sure to add the name to the library target&amp;rsquo;s dependencies as well.&lt;/p&gt;
&lt;h4 id=&#34;create-a-modulemodulemap-file&#34;&gt;Create a module.modulemap file&lt;/h4&gt;
&lt;p&gt;If using the deprecated(?) system-module command this was created for you at the top level, but when using the library initializer it has to be done by hand. This file is what really tells the compiler where to find the library. We have choices here, to make a regular header, a shim header, a bridging header, or a umbrella header&amp;hellip; I&amp;rsquo;ve gone with an umbrella header like the SwiftGD repo.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-zsh&#34; data-lang=&#34;zsh&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#91d7e3&#34;&gt;cd&lt;/span&gt; Sources
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;mkdir &lt;span style=&#34;color:#f4dbd6&#34;&gt;$SYSLIB_NAME&lt;/span&gt; &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# as referenced in the &amp;#34;name&amp;#34; parameter&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#91d7e3&#34;&gt;cd&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;$SYSLIB_NAME&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;touch module.modulemap
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;touch umbrella.h
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;module.modulemap&lt;/code&gt; contains&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;module png {
	umbrella header &amp;#34;umbrella.h&amp;#34;
	link &amp;#34;png&amp;#34;
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;code&gt;umbrella.h&lt;/code&gt; contains the one line &lt;code&gt;#include &amp;lt;png.h&amp;gt;&lt;/code&gt;&lt;/p&gt;
&lt;h3 id=&#34;if-xcode-is-having-trouble-finding-the-library&#34;&gt;If XCode is having Trouble finding the library&lt;/h3&gt;
&lt;h4 id=&#34;what-does-compiling-in-the-command-line-say&#34;&gt;What does compiling in the command line say?&lt;/h4&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;cd $PROJECT_DIR
swift package clean
swift build --verbose
&lt;/code&gt;&lt;/pre&gt;&lt;h4 id=&#34;is-package-config-installed&#34;&gt;Is &lt;code&gt;package-config&lt;/code&gt; installed?&lt;/h4&gt;
&lt;p&gt;&lt;code&gt;brew install pkg-config&lt;/code&gt;&lt;/p&gt;
&lt;h3 id=&#34;homebrew-path-correct&#34;&gt;Homebrew path correct?&lt;/h3&gt;
&lt;p&gt;When installing homebrew did you update the path? Especially important on M1 macs where the install path has changed to &lt;code&gt;/opt/homebrew/&lt;/code&gt; from &lt;code&gt;/usr/local/include/&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Check &lt;code&gt;cat ~/.zprofile&lt;/code&gt; it should exist and contain &lt;code&gt;eval &amp;quot;$(/opt/homebrew/bin/brew shellenv)&amp;quot;&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;If &lt;code&gt;~/.zprofile&lt;/code&gt; does not exist and contain that line run:
&lt;code&gt;echo &#39;eval &amp;quot;$(/opt/homebrew/bin/brew shellenv)&amp;quot;&#39; &amp;gt;&amp;gt; ~/.zprofile eval $(/opt/homebrew/bin/brew shellenv)&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Commands run:
&lt;code&gt;export HOMEBREW_PREFIX=&amp;quot;/opt/homebrew&amp;quot;; export HOMEBREW_CELLAR=&amp;quot;/opt/homebrew/Cellar&amp;quot;; export HOMEBREW_REPOSITORY=&amp;quot;/opt/homebrew&amp;quot;; export PATH=&amp;quot;/opt/homebrew/bin:/opt/homebrew/sbin${PATH+:$PATH}&amp;quot;; export MANPATH=&amp;quot;/opt/homebrew/share/man${MANPATH+:$MANPATH}:&amp;quot;; export INFOPATH=&amp;quot;/opt/homebrew/share/info:${INFOPATH:-}&amp;quot;;&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;If this command provides no output if it has already been run.&lt;/p&gt;
&lt;p&gt;To check the path: &lt;code&gt;echo $PATH&lt;/code&gt; it should now contain &lt;code&gt;/opt/homebrew/bin:/opt/homebrew/sbin:&lt;/code&gt;&lt;/p&gt;
&lt;h3 id=&#34;directory-structure&#34;&gt;Directory Structure&lt;/h3&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;-&amp;gt;Sources
 -&amp;gt;png
--- module.modulemap
--- umbrella.h
 -&amp;gt;SwiftLIBPNG
--- SwiftLIBPNG.swift
&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=&#34;package-file&#34;&gt;Package file&lt;/h3&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// swift-tools-version: 5.7&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// The swift-tools-version declares the minimum version of Swift required to build this package.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;PackageDescription&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;package&lt;/span&gt; = Package(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    name: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;SwiftLIBPNG&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    products: [
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// Products define the executables and libraries a package produces, and make them visible to other packages.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        .library(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            name: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;SwiftLIBPNG&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            targets: [&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;SwiftLIBPNG&amp;#34;&lt;/span&gt;]),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    ],
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    dependencies: [
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// Dependencies declare other packages that this package depends on.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// .package(url: /* package url */, from: &amp;#34;1.0.0&amp;#34;),&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    ],
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    targets: [
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        .systemLibrary(name: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;png&amp;#34;&lt;/span&gt;, pkgConfig: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;libpng&amp;#34;&lt;/span&gt;, providers: [.apt([&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;libpng-dev&amp;#34;&lt;/span&gt;]), .brew([&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;libpng&amp;#34;&lt;/span&gt;])]),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        .target(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            name: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;SwiftLIBPNG&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            dependencies: [&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;png&amp;#34;&lt;/span&gt;]),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        .testTarget(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            name: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;SwiftLIBPNGTests&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            dependencies: [&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;SwiftLIBPNG&amp;#34;&lt;/span&gt;]),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    ]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description>
    </item>
    
    
    
    <item>
      <title>But some of my best friends are C</title>
      <link>https://whynotestflight.com/excuses/but-some-of-my-best-friends-are-c/</link>
      <pubDate>Sat, 11 Mar 2023 00:00:00 +0000</pubDate>
      
      <guid>https://whynotestflight.com/excuses/but-some-of-my-best-friends-are-c/</guid>
      <description>&lt;p&gt;So I have a goal for a Swift mastodon bot: post an generated image per dayish while running on a Linux (explicitly Ubuntu) box.&lt;/p&gt;
&lt;p&gt;So if I was going to run tipsy robot on MacOS I&amp;rsquo;d be done by now. There are a lot of really useful types for working with image information (UIImage, CGImage, CVBuffer, Metal). None of these work on Linux.&lt;/p&gt;
&lt;p&gt;There are libraries for creating noise in GameKit, also not available on Linux.&lt;/p&gt;
&lt;p&gt;If I was interested in using other people libraries, I would also be done by now. I am clearly not the first one to run into this problem. In fact I learned a lot from looking at a package that I might ultimately use, the &lt;a href=&#34;https://github.com/twostraws/SwiftGD&#34;&gt;HackingWithSwift GD wrapper&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;But since this is more of a research project I&amp;rsquo;m going to see about writing it all myself.&lt;/p&gt;
&lt;p&gt;Before I can write a file, I need to have the buffer of random pixel info to put into it. My favorite noise function all are written in C. What is a Swift programer to do?&lt;/p&gt;
&lt;p&gt;It turns out it is pretty easy to either:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Embed the code in the Swift project directly using a bridging header.&lt;/li&gt;
&lt;li&gt;Put the C in a library, with or without some Swift code to help the user.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;embed-the-code&#34;&gt;Embed the Code&lt;/h2&gt;
&lt;p&gt;I followed the tutorial here:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://theswiftdev.com/how-to-call-c-code-from-swift/&#34;&gt;https://theswiftdev.com/how-to-call-c-code-from-swift/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;to make make the following almost empty sample project&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/carlynorama/DirectIncludeC&#34;&gt;https://github.com/carlynorama/DirectIncludeC&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;To flesh it out a little the steps to add C to an existing project are:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;File &amp;gt; NewFile, Choose C type&lt;/li&gt;
&lt;li&gt;Name the file what you want. DO NOT include .c in the same.&lt;/li&gt;
&lt;li&gt;DO tick the box let Xcode make the header file.&lt;/li&gt;
&lt;li&gt;If is the first C file added, X-code will ask if you want to add a bridging header. Say yes.&lt;/li&gt;
&lt;li&gt;3 new files will be in the Xcode project
&lt;ul&gt;
&lt;li&gt;your_name.c&lt;/li&gt;
&lt;li&gt;your_name.h&lt;/li&gt;
&lt;li&gt;ProjectName-Bridging-Header.h&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Add your_name.h to the bridging header.&lt;/li&gt;
&lt;li&gt;Add code, call it directly from a .swift file, celebrate.&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id=&#34;trouble-shooting&#34;&gt;Trouble shooting&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;Build input file cannot be found: &#39;File/Path/ProjectName-Bridging-Header.h&#39;. Did you forget to declare this file as an output of a script phase or custom build rule which produces it?&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;If you make the Bridging-Header by hand XCode can&amp;rsquo;t always find it. Try moving it to the root of the project. If that works you can either leave it and move on &amp;hellip; OR&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;open Project Settings&lt;/li&gt;
&lt;li&gt;Select Target, if necessary&lt;/li&gt;
&lt;li&gt;Open Build Settings&lt;/li&gt;
&lt;li&gt;Filter on &amp;ldquo;Bridging&amp;rdquo; and a setting with the name &amp;ldquo;Objective-C Bridging Header&amp;rdquo; comes up.&lt;/li&gt;
&lt;li&gt;Make sure the text in this field is the correct path relative to your project&amp;rsquo;s root. So either &lt;code&gt;ProjectName-Bridging-Header.h&lt;/code&gt; if you want it in the root, or &lt;code&gt;ProjectName/ProjectName-Bridging-Header.h&lt;/code&gt; if the project directory is where you want it.&lt;/li&gt;
&lt;/ol&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;Linker command failed with exit code 1 (use -v to see invocation)&lt;/code&gt; paired with &lt;code&gt;1 duplicate symbol for architecture x86_641&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;There is a function that is defined twice. Did you swap the content for the .c and the .h files when you pasted the code in if bringing it form somewhere else? Ask me how I know. I mean don&amp;rsquo;t. Really.&lt;/p&gt;
&lt;h3 id=&#34;a-little-more-about-the-bridging-headers&#34;&gt;A little more about the Bridging Header&amp;rsquo;s&lt;/h3&gt;
&lt;p&gt;The bridging header is where XCode looks for the functions you want to make available to the rest of the project. You can just add all the function, or have separate headers for functions that only the C/Objective-C can use and ones to expose to Swift. It does NOT appear that C++ headers are directly usable (&lt;a href=&#34;https://www.swift.org/cxx-interop-workgroup/&#34;&gt;yet?&lt;/a&gt;), but C++ can be wrapped in Objective-C or C for use.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Great StackOverflow answer on &lt;a href=&#34;https://stackoverflow.com/questions/32541268/can-i-have-swift-objective-c-c-and-c-files-in-the-same-xcode-project/32546879#32546879&#34;&gt;mixing several code types into one project&lt;/a&gt; with &lt;a href=&#34;https://github.com/SwiftArchitect/SO-32541268/tree/master/SO-32541268&#34;&gt;sample code&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;compile faster &lt;a href=&#34;https://www.swift.org/blog/bridging-pch/&#34;&gt;https://www.swift.org/blog/bridging-pch/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;put-code-in-a-package&#34;&gt;Put Code in a Package&lt;/h2&gt;
&lt;p&gt;My preferred approach is to put the C code into a package, paired with some Swift code to make accessing it easier.&lt;/p&gt;
&lt;p&gt;There is an example project, &lt;a href=&#34;https://github.com/carlynorama/NoiseMaker&#34;&gt;NoiseMaker&lt;/a&gt;, that compiles but doesn&amp;rsquo;t actually do anything useful yet.&lt;/p&gt;
&lt;p&gt;The default behavior of the swift compiler is to look for the headers in a folder called include. This is changeable? sort of? but honestly looks like a real pain so I&amp;rsquo;m just going to go with the Swifty Way.&lt;/p&gt;
&lt;h3 id=&#34;references&#34;&gt;References&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://theswiftdev.com/how-to-call-c-code-from-swift/&#34;&gt;https://theswiftdev.com/how-to-call-c-code-from-swift/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://theswiftdev.com/how-to-use-c-libraries-in-swift/&#34;&gt;https://theswiftdev.com/how-to-use-c-libraries-in-swift/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://www.hackingwithswift.com/articles/87/how-to-wrap-a-c-library-in-swift&#34;&gt;https://www.hackingwithswift.com/articles/87/how-to-wrap-a-c-library-in-swift&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://dev.to/ksemianov/how-to-create-a-swift-package-from-a-c-library-3g2l&#34;&gt;https://dev.to/ksemianov/how-to-create-a-swift-package-from-a-c-library-3g2l&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;directory-structure&#34;&gt;Directory Structure&lt;/h3&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;-&amp;gt;Sources
 -&amp;gt;C
  -&amp;gt;include
---- my_name.h
--- my_name.c
 -&amp;gt;Swift
--- MyWrapper.swift
&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=&#34;package-file&#34;&gt;Package File&lt;/h3&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// swift-tools-version: 5.7&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// The swift-tools-version declares the minimum version of Swift required to build this package.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;PackageDescription&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;package&lt;/span&gt; = Package(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    name: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;NoiseMaker&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    products: [
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// Products define the executables and libraries a package produces, and make them visible to other packages.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        .library(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            name: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;NoiseMaker&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            targets: [&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;CNoiseMaker&amp;#34;&lt;/span&gt;,&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;NoiseMaker&amp;#34;&lt;/span&gt;]),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    ],
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    dependencies: [
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// Dependencies declare other packages that this package depends on.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// .package(url: /* package url */, from: &amp;#34;1.0.0&amp;#34;),&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    ],
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    targets: [
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// Targets are the basic building blocks of a package. A target can define a module or a test suite.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// Targets can depend on other targets in this package, and on products in packages this package depends on.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        .target(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            name: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;CNoiseMaker&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            path: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Sources/C&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            ),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        .target(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            name: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;NoiseMaker&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            dependencies: [&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;CNoiseMaker&amp;#34;&lt;/span&gt;],
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            path: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Sources/Swift&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        )
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    ]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description>
    </item>
    
    
    
    <item>
      <title>A picture takes 1000 words</title>
      <link>https://whynotestflight.com/excuses/a-picture-takes-1000-words/</link>
      <pubDate>Sat, 18 Feb 2023 00:00:00 +0000</pubDate>
      
      <guid>https://whynotestflight.com/excuses/a-picture-takes-1000-words/</guid>
      <description>&lt;p&gt;So, I can post a simple message, what about a picture? That turned out to be a bit of a headache, dragging out of storage 20 year old memories of scraping email data with Perl.&lt;/p&gt;
&lt;p&gt;Oh, Form data. Sigh.&lt;/p&gt;
&lt;p&gt;I created a command line testing tool for some of the ideas before they go into APItizer called &lt;a href=&#34;https://github.com/carlynorama/APIng&#34;&gt;APIng&lt;/a&gt;. More notes are there.&lt;/p&gt;
&lt;h2 id=&#34;references&#34;&gt;References&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Form Data Spec: &lt;a href=&#34;https://www.rfc-editor.org/rfc/rfc7578&#34;&gt;https://www.rfc-editor.org/rfc/rfc7578&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://html.spec.whatwg.org/multipage/forms.html&#34;&gt;https://html.spec.whatwg.org/multipage/forms.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://www.digitalocean.com/community/tutorials/workflow-resizing-images-with-imagemagick&#34;&gt;https://www.digitalocean.com/community/tutorials/workflow-resizing-images-with-imagemagick&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://stackoverflow.com/questions/55361096/upload-image-with-multipart-form-data-only-in-swift-4-2&#34;&gt;https://stackoverflow.com/questions/55361096/upload-image-with-multipart-form-data-only-in-swift-4-2&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://stackoverflow.com/questions/4526273/what-does-enctype-multipart-form-data-mean/28380690#28380690&#34;&gt;https://stackoverflow.com/questions/4526273/what-does-enctype-multipart-form-data-mean/28380690#28380690&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;testing-calls&#34;&gt;Testing Calls&lt;/h2&gt;
&lt;h3 id=&#34;making-tiny-test-images&#34;&gt;Making Tiny Test Images&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;brew install imagemagick&lt;/code&gt; if necessary&lt;/li&gt;
&lt;li&gt;&lt;code&gt;convert original.png -resize 10x10^ -gravity center -extent 5x5 new.png&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;using-netcat&#34;&gt;Using &lt;a href=&#34;https://en.wikipedia.org/wiki/Netcat&#34;&gt;NetCat&lt;/a&gt;&lt;/h3&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-zsh&#34; data-lang=&#34;zsh&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# Start up netcat on port 8080 &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        nc -l -p &lt;span style=&#34;color:#f5a97f&#34;&gt;8080&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# if that does not work try, but that means calls will only resolve at http://localhost:8080&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        nc -l localhost &lt;span style=&#34;color:#f5a97f&#34;&gt;8080&lt;/span&gt;  
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# or &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        brew install netcat
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        netcat -l -p &lt;span style=&#34;color:#f5a97f&#34;&gt;8080&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# live dangerously if you get sick of restarting it&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;# You might have to ^C a few times to catch it during a sleep&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;while&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;[&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;1&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;]&lt;/span&gt; ; &lt;span style=&#34;color:#c6a0f6&#34;&gt;do&lt;/span&gt; ; netcat -l -p &lt;span style=&#34;color:#f5a97f&#34;&gt;8080&lt;/span&gt; ; sleep &lt;span style=&#34;color:#f5a97f&#34;&gt;1&lt;/span&gt; ; &lt;span style=&#34;color:#c6a0f6&#34;&gt;done&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Go to &lt;code&gt;http://localhost:8080&lt;/code&gt; and see the call show up there, run curl commands from a different terminal, etc. NetCat does not respond so make sure to include timeouts for calls that will wait for a response.&lt;/p&gt;
&lt;h3 id=&#34;checking-parsing&#34;&gt;Checking Parsing&lt;/h3&gt;
&lt;p&gt;Does it parse? Service that will reply with json about what it thinks it got back semantically, rather than just a reflection.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://httpbin.org/post&#34;&gt;https://httpbin.org/post&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;curl-examples-to-crib-from&#34;&gt;cURL Examples To Crib From&lt;/h3&gt;
&lt;p&gt;cURL commands sent to BOTH NetCat and httpbin can be very instructive on what your code should be doing.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;curl -s -X POST &#39;https://httpbin.org/post&#39; --form foo=&amp;quot;bar&amp;quot; --form file=&amp;quot;@very_small_test.png&amp;quot;&lt;/code&gt;  will let you see the form data as sent.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;curl -s -X POST http://localhost:8080 --form foo=&amp;quot;bar&amp;quot; --form file=&amp;quot;@very_small_test.png&amp;quot;&lt;/code&gt; will let you see how a server will typically parse it. Note that the image is parsed as an attachment NOT form data.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;mistakes-were-made&#34;&gt;Mistakes were made&lt;/h2&gt;
&lt;p&gt;To post an image on Mastodon, FIRST comes posting the image file(s), getting back the ID(s) and then using the returned data to make a status post. I kept doing SOMETHING wrong. So this is why there is that reminder above that &lt;a href=&#34;https://en.wikipedia.org/wiki/Netcat&#34;&gt;NetCat&lt;/a&gt; and &lt;a href=&#34;https://httpbin.org/&#34;&gt;https://httpbin.org/&lt;/a&gt; are your friends. I looked into &lt;a href=&#34;https://www.postman.com&#34;&gt;Postman&lt;/a&gt;, but it is ginormous.&lt;/p&gt;
&lt;h3 id=&#34;first-when-posting-the-image-file&#34;&gt;First, when posting the image file&amp;hellip;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;I was missing the extra &amp;ldquo;&amp;ndash;&amp;rdquo; from the end of my form boundary&lt;/li&gt;
&lt;li&gt;I was leaving the fileName field off of my image data encoding b/c Mastodon didn&amp;rsquo;t appear to be using it. That sent it as inline text encoding instead of as an attachment and it needed to be an attachment.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;second-when-adding-the-mediaids&#34;&gt;Second when adding the MediaIDs&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;encoding an array for URLEncoded data generally looks like &lt;code&gt;arrayName[]=value0&amp;amp;arrayName[]=value1&lt;/code&gt; not &lt;code&gt;arrayName=[value0,value1]&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;arrayToQueryItems&lt;/span&gt;(baseStringForKey:&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;, array:[CustomStringConvertible]) -&amp;gt; [URLQueryItem] {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;queries&lt;/span&gt;:[URLQueryItem] = []
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        queries.reserveCapacity(array.&lt;span style=&#34;color:#91d7e3&#34;&gt;count&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;for&lt;/span&gt; item &lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt; array {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            queries.append(URLQueryItem(name: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;baseStringForKey&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;[]&amp;#34;&lt;/span&gt;, value: &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;(describing: item)))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; queries
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;the-background-code-in-apitizer&#34;&gt;The background code in APItizer&lt;/h2&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//  APItizer&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//  https://github.com/carlynorama/APItizer&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//  MultiPartFormEncoder.swift&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//  Created by Carlyn Maw on 2/13/23.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;Foundation&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;MARK:&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt; Multipart Form Encoding&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//https://www.rfc-editor.org/rfc/rfc7578&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;enum&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;MultiPartFormEncoder&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;header&lt;/span&gt;(boundary:&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;) -&amp;gt; [&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;:&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;] {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        [&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Content-Type&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;multipart/form-data; boundary=&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;boundary&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;makeBodyData&lt;/span&gt;(formItems:&lt;span style=&#34;color:#91d7e3&#34;&gt;Dictionary&lt;/span&gt;&amp;lt;&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;, CustomStringConvertible&amp;gt;, withTermination:&lt;span style=&#34;color:#91d7e3&#34;&gt;Bool&lt;/span&gt; = &lt;span style=&#34;color:#f5a97f&#34;&gt;true&lt;/span&gt;) &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; -&amp;gt; (boundary:&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;, body:Data) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;boundary&lt;/span&gt; = &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Boundary--&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;UUID&lt;span style=&#34;color:#a6da95&#34;&gt;()&lt;/span&gt;.uuidString&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;bodyData&lt;/span&gt; = Data()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;for&lt;/span&gt; (key, value) &lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt; formItems {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            bodyData = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; appendTextField(data: bodyData, label: key, value: &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;(describing: value), boundary: boundary)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; withTermination {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            bodyData = appendTerminationBoundary(data: bodyData, boundary: boundary)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; (boundary, bodyData)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//Media uploads will fail if fileName is not included, regardless of MIME/Type.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;makeBodyData&lt;/span&gt;(stringItems:&lt;span style=&#34;color:#91d7e3&#34;&gt;Dictionary&lt;/span&gt;&amp;lt;&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;, CustomStringConvertible&amp;gt;, attachments:[&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;:Attachable], withTermination:&lt;span style=&#34;color:#91d7e3&#34;&gt;Bool&lt;/span&gt; = &lt;span style=&#34;color:#f5a97f&#34;&gt;true&lt;/span&gt;) &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; -&amp;gt; (boundary:&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;, body:Data) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;boundary&lt;/span&gt; = &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Boundary--&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;UUID&lt;span style=&#34;color:#a6da95&#34;&gt;()&lt;/span&gt;.uuidString&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;bodyData&lt;/span&gt; = Data()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;for&lt;/span&gt; (key, value) &lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt; stringItems {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            bodyData = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; appendTextField(data: bodyData, label: key, value: &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;(describing: value), boundary: boundary)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;for&lt;/span&gt; (key, value) &lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt; attachments {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            bodyData = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; appendDataField(data: bodyData, label: key, dataToAdd: value.data, mimeType: value.mimeType, fileName: value.fileName, boundary: boundary)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; withTermination {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            bodyData = appendTerminationBoundary(data: bodyData, boundary: boundary)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; (boundary, bodyData)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;TODO:&lt;/span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt; All this copying... inout instead? make extension?&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;appendTextField&lt;/span&gt;(data:Data, label key: &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;, value: &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;, boundary:&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;) &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; -&amp;gt; Data {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;copy&lt;/span&gt; = data
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;formFieldData&lt;/span&gt; = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; textFormField(label:key, value:value, boundary:boundary)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        copy.append(formFieldData)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; copy
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;appendDataField&lt;/span&gt;(data:Data, label key: &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;, dataToAdd: Data, mimeType: &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;, fileName:&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;? = &lt;span style=&#34;color:#f5a97f&#34;&gt;nil&lt;/span&gt;, boundary:&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;) &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; -&amp;gt; Data {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;copy&lt;/span&gt; = data
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;formFieldData&lt;/span&gt; = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; dataFormField(label:key, data: dataToAdd, mimeType: mimeType, fileName:fileName, boundary:boundary)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        copy.append(formFieldData)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; copy
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;appendEncodable&lt;/span&gt;&amp;lt;T:Encodable&amp;gt;(data:Data, object:T, boundary:&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;) &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; -&amp;gt; Data {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;copy&lt;/span&gt; = data
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;queries&lt;/span&gt; = QueryEncoder.makeQueryItems(from: object)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;for&lt;/span&gt; query &lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt; queries {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;value&lt;/span&gt; = query.value {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                copy.append(&lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; textFormField(label: query.name, value: value, boundary: boundary))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; copy
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;appendTerminationBoundary&lt;/span&gt;(data:Data, boundary:&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;) -&amp;gt; Data {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;copy&lt;/span&gt; = data
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;boundaryData&lt;/span&gt; = &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;--&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;boundary&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;--&amp;#34;&lt;/span&gt;.data(using: .utf8)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        copy.append(boundaryData!) &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//TODO throw instead&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; copy
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;textFormField&lt;/span&gt;(label key: &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;, value: &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;, boundary:&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;) &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; -&amp;gt; Data {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;fieldString&lt;/span&gt; = &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;--&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;boundary&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\r\n&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        fieldString &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;+=&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Content-Disposition: form-data; name=&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;key&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\&amp;#34;\r\n&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        fieldString &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;+=&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Content-Type: text/plain; charset=UTF-8&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\r\n&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        fieldString &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;+=&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\r\n&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        fieldString &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;+=&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;value&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\r\n&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;       &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;fieldData&lt;/span&gt; = fieldString.data(using: .utf8)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;       &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; fieldData == &lt;span style=&#34;color:#f5a97f&#34;&gt;nil&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;throw&lt;/span&gt; APItizerError(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;couldn&amp;#39;t make data from field &lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;key&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;, &lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;value&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt; with &lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;boundary&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;       }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; fieldData!
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;dataFormField&lt;/span&gt;(label key: &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;, data: Data, mimeType: &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;, fileName:&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;? = &lt;span style=&#34;color:#f5a97f&#34;&gt;nil&lt;/span&gt;, boundary:&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;) &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; -&amp;gt; Data {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;fieldData&lt;/span&gt; = Data()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; fieldData.append(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;--&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;boundary&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\r\n&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;fileName&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; fieldData.append(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Content-Disposition: form-data; name=&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;key&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;; filename=&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;fileName&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;;&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\r\n&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        } &lt;span style=&#34;color:#c6a0f6&#34;&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; fieldData.append(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Content-Disposition: form-data; name=&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;key&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\&amp;#34;\r\n&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; fieldData.append(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Content-Type: &lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;mimeType&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\r\n&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; fieldData.append(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\r\n&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        fieldData.append(data)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; fieldData.append(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\r\n&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; fieldData &lt;span style=&#34;color:#c6a0f6&#34;&gt;as&lt;/span&gt; Data
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Struct -&amp;gt; Dictionary helpers&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//  APItizer&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//  https://github.com/carlynorama/APItizer&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//  DictionaryEncoder.swift&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//  Created by Carlyn Maw on 2/13/23.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;Foundation&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;enum&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;DictionaryEncoder&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;makeDictionary&lt;/span&gt;(from itemToEncode:&lt;span style=&#34;color:#91d7e3&#34;&gt;Any&lt;/span&gt;) -&amp;gt; [&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;:&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;]? {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;mirror&lt;/span&gt; = Mirror(reflecting: itemToEncode)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;dictionary&lt;/span&gt;:[&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;:&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;] = [:]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;for&lt;/span&gt; child &lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt; mirror.children  {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;key&lt;/span&gt;:&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt; = child.label {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// print(&amp;#34;key: \(key), value: \(child.value)&amp;#34;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// print(child.value)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// print(String(describing: child.value))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; child.value &lt;span style=&#34;color:#c6a0f6&#34;&gt;is&lt;/span&gt; ExpressibleByNilLiteral  {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;typeDescription&lt;/span&gt; = object_getClass(child.value)?.description() ?? &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;!&lt;/span&gt;typeDescription.&lt;span style=&#34;color:#91d7e3&#34;&gt;contains&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Null&amp;#34;&lt;/span&gt;) &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;!&lt;/span&gt;typeDescription.&lt;span style=&#34;color:#91d7e3&#34;&gt;contains&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Empty&amp;#34;&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; (&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt;, some) = Mirror(reflecting: child.value).children.&lt;span style=&#34;color:#91d7e3&#34;&gt;first&lt;/span&gt;!
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//print(some)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                        dictionary[key] = &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;(describing: some)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                } &lt;span style=&#34;color:#c6a0f6&#34;&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    dictionary[key] = &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;(describing: child.value)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;else&lt;/span&gt; { &lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;No key.&amp;#34;&lt;/span&gt;) }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; dictionary
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//Look at QueryEncoder for other clean up tasks.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;makeDictionary&lt;/span&gt;(fromEncodable itemToEncode:Encodable) -&amp;gt; [&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;:&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;] {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;encoder&lt;/span&gt; = JSONEncoder()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;encode&lt;/span&gt;&amp;lt;T&amp;gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; value: T) &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; -&amp;gt; [&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;: &lt;span style=&#34;color:#91d7e3&#34;&gt;Any&lt;/span&gt;] &lt;span style=&#34;color:#c6a0f6&#34;&gt;where&lt;/span&gt; T : Encodable {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;data&lt;/span&gt; = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; encoder.encode(value)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; JSONSerialization.jsonObject(with: data, options: .allowFragments) &lt;span style=&#34;color:#c6a0f6&#34;&gt;as&lt;/span&gt;! [&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;: &lt;span style=&#34;color:#91d7e3&#34;&gt;Any&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;guard&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;dictionary&lt;/span&gt; = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt;? encode(itemToEncode) &lt;span style=&#34;color:#c6a0f6&#34;&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//print(&amp;#34;got nothing&amp;#34;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; [:]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;cleanedUp&lt;/span&gt;:[&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;:&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;] = [:]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;for&lt;/span&gt; (key, value) &lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt; dictionary {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;stringValue&lt;/span&gt; = &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;value&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; stringValue == &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;(&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\n&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;)&amp;#34;&lt;/span&gt; { stringValue = &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; stringValue.hasPrefix(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;(&amp;#34;&lt;/span&gt;) { stringValue = stringValue.trimmingCharacters(&lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt;: CharacterSet(charactersIn: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;()&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\n&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;))}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//print(stringValue)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;!&lt;/span&gt;stringValue.&lt;span style=&#34;color:#91d7e3&#34;&gt;isEmpty&lt;/span&gt;  {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                cleanedUp[key] = &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;stringValue&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; cleanedUp
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Oh and then actually posting&amp;hellip;&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;post_FormBody&lt;/span&gt;(baseUrl:URL, formData:&lt;span style=&#34;color:#91d7e3&#34;&gt;Dictionary&lt;/span&gt;&amp;lt;&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;, CustomStringConvertible&amp;gt;, withAuth:&lt;span style=&#34;color:#91d7e3&#34;&gt;Bool&lt;/span&gt; = &lt;span style=&#34;color:#f5a97f&#34;&gt;true&lt;/span&gt;) async &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; -&amp;gt; Data {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; (boundary, dataToSend) = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; MultiPartFormEncoder.makeBodyData(formItems: formData, withTermination: &lt;span style=&#34;color:#f5a97f&#34;&gt;true&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; await post_FormBody(baseUrl:baseUrl, dataToSend:dataToSend, boundary: boundary, withAuth: withAuth)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;post_FormBody&lt;/span&gt;(baseUrl:URL, dataToSend:Data, boundary:&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;, withAuth:&lt;span style=&#34;color:#91d7e3&#34;&gt;Bool&lt;/span&gt; = &lt;span style=&#34;color:#f5a97f&#34;&gt;true&lt;/span&gt;) async &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; -&amp;gt; Data {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//cachePolicy: URLRequest.CachePolicy, timeoutInterval: TimeInterval&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;request&lt;/span&gt; = URLRequest(url: baseUrl)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        request.httpMethod = &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;POST&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; withAuth { &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; addAuth(request: &amp;amp;request) }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//necessary b/c not the default on upload. See APIng&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        request.setValue(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;multipart/form-data; boundary=&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;boundary&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;, forHTTPHeaderField: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Content-Type&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; await requestService.postData(urlRequest: request, data: dataToSend)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;With the same posting code over in the &lt;code&gt;RequestService&lt;/code&gt; from last week since all the heavy lifting is in the &lt;code&gt;URLRequest&lt;/code&gt; and the &lt;code&gt;Data&lt;/code&gt;.&lt;/p&gt;
</description>
    </item>
    
    
    
    <item>
      <title>Well clearly I need bot minions first</title>
      <link>https://whynotestflight.com/excuses/well-clearly-i-need-bot-minions-first/</link>
      <pubDate>Sat, 11 Feb 2023 00:00:00 +0000</pubDate>
      
      <guid>https://whynotestflight.com/excuses/well-clearly-i-need-bot-minions-first/</guid>
      <description>&lt;p&gt;So Twitter announced the demise of the bot API so clearly it&amp;rsquo;s time to make bots for Mastodon. I&amp;rsquo;m not super comfortable on social media. This is maybe the way for me.&lt;/p&gt;
&lt;p&gt;It look ~20 minutes to do &lt;a href=&#34;https://thecodingtrain.com/tracks/mastodon/mastodon/setting-up-a-mastodon-bot&#34;&gt;hello-mastodon-bot&lt;/a&gt; in JavaScript, how long can it possibly take in Swift?&lt;/p&gt;
&lt;p&gt;Well, not long as well if you&amp;rsquo;re smart enough to use a library, I&amp;rsquo;m guessing. I am not that smart.&lt;/p&gt;
&lt;p&gt;One week later and I am still not done.&lt;/p&gt;
&lt;h2 id=&#34;steps-so-far&#34;&gt;Steps so far&lt;/h2&gt;
&lt;h3 id=&#34;package-things-up&#34;&gt;Package things up&lt;/h3&gt;
&lt;p&gt;First I split &lt;a href=&#34;https://github.com/carlynorama/ActivityPubExplorer&#34;&gt;ActivityPubExplorer&lt;/a&gt; into a Mastodon Client called &lt;a href=&#34;https://github.com/carlynorama/TrunkLine&#34;&gt;TrunkLine&lt;/a&gt; and a generic API Client &lt;a href=&#34;https://github.com/carlynorama/APItizer&#34;&gt;APItizer&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Just getting a new testing app up and running back to where ActivityPubExplorer with the new packages took some time.&lt;/p&gt;
&lt;p&gt;These libraries at that point are read-only protocols no authorizations.&lt;/p&gt;
&lt;h3 id=&#34;start-a-cli-project&#34;&gt;Start a CLI Project&lt;/h3&gt;
&lt;p&gt;Then it was getting to Hello-World in a CLI. Here are the notes from the &lt;a href=&#34;https://github.com/carlynorama/tipsy-robot-swift&#34;&gt;tispy-robot-swift&lt;/a&gt; repo README as of today.&lt;/p&gt;
&lt;h4 id=&#34;assumptions&#34;&gt;Assumptions:&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;You have an application token&lt;/li&gt;
&lt;li&gt;If using VSCODE  extension &lt;code&gt;sswg.swift-lang&lt;/code&gt; has been installed&lt;/li&gt;
&lt;li&gt;Swift 5.7 is installed on the machine (check with &lt;code&gt;swift --version&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;A gitignore with the items in &lt;code&gt;gitignore_example.txt&lt;/code&gt; (&lt;code&gt;.env&lt;/code&gt;!!!)&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&#34;writing-a-new-bot&#34;&gt;Writing a New Bot:&lt;/h4&gt;
&lt;p&gt;If you&amp;rsquo;d like to start from scratch, here are the steps&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Run the following commands to get the bot executable started and verify that it can build:&lt;/li&gt;
&lt;/ol&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-zsh&#34; data-lang=&#34;zsh&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    mkdir your_bot_project_name
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#91d7e3&#34;&gt;cd&lt;/span&gt; your_bot_project_name
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    swift package init --type executable
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    swift run                                   &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;#will see Hello, world! in console. &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ol start=&#34;2&#34;&gt;
&lt;li&gt;Update the &lt;code&gt;Package.swift&lt;/code&gt; to include &lt;code&gt;ArgumentParser&lt;/code&gt; and &lt;code&gt;TrunkLine&lt;/code&gt; or some other MastodonAPI library. See this projects &lt;code&gt;Package.swift&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Since &lt;code&gt;TrunkLine&lt;/code&gt; requires &lt;code&gt;.macOS(.v12)&lt;/code&gt; for now, so does this example.&lt;/p&gt;
&lt;p&gt;Also note that the reference to &lt;code&gt;TrunkLine&lt;/code&gt; references a branch instead of a version number because it is my library and it&amp;rsquo;s under development in tandem with this project. If working on a library at the same time as using it in a project &lt;code&gt;swift package update&lt;/code&gt; forces your project to go fetch the newest version. If that still is not enough, delete the &lt;code&gt;.build&lt;/code&gt; folder, but that may be an indicator&lt;/p&gt;
&lt;ol start=&#34;3&#34;&gt;
&lt;li&gt;Note that the &lt;code&gt;swift package init&lt;/code&gt; command created two directories (&lt;code&gt;Sources/your_bot_project_name&lt;/code&gt;) and made a file called &lt;code&gt;your_bot_project_name.swift&lt;/code&gt; in that file is a function that looks like:&lt;/li&gt;
&lt;/ol&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    @main
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;your_bot_project_name&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;private&lt;/span&gt;(&lt;span style=&#34;color:#c6a0f6&#34;&gt;set&lt;/span&gt;) &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;text&lt;/span&gt; = &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Hello, World!&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;main&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(your_bot_project_name().text)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Some people change this and just have a &lt;code&gt;main.swift&lt;/code&gt; file in the &lt;code&gt;Sources/your_bot_project_name&lt;/code&gt; directory which then is the contents of their &lt;code&gt;@main&lt;/code&gt; function.&lt;/p&gt;
&lt;p&gt;Change the contents of that file to match the contents of &lt;code&gt;hello_server_example.swift&lt;/code&gt; and try &lt;code&gt;swift run&lt;/code&gt;. Your bot should have posted!&lt;/p&gt;
&lt;h4 id=&#34;references--resources&#34;&gt;References &amp;amp; Resources&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://www.youtube.com/watch?v=pQt71tLmiac&#34;&gt;Swift Command Line with Argument Parser&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://www.swift.org/blog/argument-parser/&#34;&gt;https://www.swift.org/blog/argument-parser/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://swiftpackageindex.com/apple/swift-argument-parser/1.2.1/documentation/argumentparser/gettingstarted&#34;&gt;https://swiftpackageindex.com/apple/swift-argument-parser/1.2.1/documentation/argumentparser/gettingstarted&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/carlynorama/tipsy-robot&#34;&gt;https://github.com/carlynorama/tipsy-robot&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;getting-the-token-into-the-environment&#34;&gt;Getting the token into the environment&lt;/h3&gt;
&lt;p&gt;To use a bot or any client app to post, there needs to be Authentication &amp;amp; Authorization. Once you have a token, it&amp;rsquo;s a mistake to keep it in the repo and a pain to keep copying it.&lt;/p&gt;
&lt;p&gt;Here is the simplest code to make that work. In the APItizer package it works with the Keychain as well now.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//---------------------------------------------- C getenv &amp;amp; setenv work!&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;getEnvironmentVar&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; name: &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;) -&amp;gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;? {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;guard&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;rawValue&lt;/span&gt; = getenv(name) &lt;span style=&#34;color:#c6a0f6&#34;&gt;else&lt;/span&gt; { &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;nil&lt;/span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;(utf8String: rawValue)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;setEnvironment&lt;/span&gt;(key:&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;, value:&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;, overwrite: &lt;span style=&#34;color:#91d7e3&#34;&gt;Bool&lt;/span&gt; = &lt;span style=&#34;color:#f5a97f&#34;&gt;false&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    setenv(key, value, overwrite ? &lt;span style=&#34;color:#f5a97f&#34;&gt;1&lt;/span&gt; : &lt;span style=&#34;color:#f5a97f&#34;&gt;0&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;setEnvironment(key: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;SECRET1&amp;#34;&lt;/span&gt;, value: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;(whispers I cant hear)&amp;#34;&lt;/span&gt;, overwrite: &lt;span style=&#34;color:#f5a97f&#34;&gt;true&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(getEnvironmentVar(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;SECRET1&amp;#34;&lt;/span&gt;) ?? &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;nothing&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//-------------------------------------------------- mini dotEnv handling&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;loadDotEnv&lt;/span&gt;() &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;url&lt;/span&gt; = URL(fileURLWithPath: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;.env&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;guard&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;envString&lt;/span&gt; = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt;? &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;(contentsOf: url) &lt;span style=&#34;color:#c6a0f6&#34;&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;       &lt;span style=&#34;color:#91d7e3&#34;&gt;fatalError&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;no env file data&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    envString
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        .trimmingCharacters(&lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt;: .newlines)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        .&lt;span style=&#34;color:#91d7e3&#34;&gt;split&lt;/span&gt;(separator: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\n&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        .&lt;span style=&#34;color:#c6a0f6&#34;&gt;lazy&lt;/span&gt; &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//may or maynot save anything&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        .&lt;span style=&#34;color:#91d7e3&#34;&gt;filter&lt;/span&gt;({&lt;span style=&#34;color:#f4dbd6&#34;&gt;$0&lt;/span&gt;.&lt;span style=&#34;color:#c6a0f6&#34;&gt;prefix&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;1&lt;/span&gt;) &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;!=&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;#&amp;#34;&lt;/span&gt;})  &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//is comment&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        .&lt;span style=&#34;color:#91d7e3&#34;&gt;map&lt;/span&gt;({ &lt;span style=&#34;color:#f4dbd6&#34;&gt;$0&lt;/span&gt;.&lt;span style=&#34;color:#91d7e3&#34;&gt;split&lt;/span&gt;(separator: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;=&amp;#34;&lt;/span&gt;).&lt;span style=&#34;color:#91d7e3&#34;&gt;map&lt;/span&gt;({&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;(&lt;span style=&#34;color:#f4dbd6&#34;&gt;$0&lt;/span&gt;.trimmingCharacters(&lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt;: CharacterSet(charactersIn:&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\&amp;#34;\&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;)))}) })
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        .forEach({  addToEnv(result: &lt;span style=&#34;color:#f4dbd6&#34;&gt;$0&lt;/span&gt;) })
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;addToEnv&lt;/span&gt;(result:&lt;span style=&#34;color:#91d7e3&#34;&gt;Array&lt;/span&gt;&amp;lt;&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;&amp;gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; result.&lt;span style=&#34;color:#91d7e3&#34;&gt;count&lt;/span&gt; == &lt;span style=&#34;color:#f5a97f&#34;&gt;2&lt;/span&gt;  {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            setEnvironment(key: result[&lt;span style=&#34;color:#f5a97f&#34;&gt;0&lt;/span&gt;], value: result[&lt;span style=&#34;color:#f5a97f&#34;&gt;1&lt;/span&gt;], overwrite: &lt;span style=&#34;color:#f5a97f&#34;&gt;true&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        } &lt;span style=&#34;color:#c6a0f6&#34;&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//item would of had to have contained more than 1 &amp;#34;=&amp;#34; or none at all. I&amp;#39;d like to know about that for now. &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Failed dotenv add: &lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;result&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;) 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;do&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; loadDotEnv()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;value&lt;/span&gt; = ProcessInfo.processInfo.environment[&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;SECRET&amp;#34;&lt;/span&gt;] {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(value)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    } &lt;span style=&#34;color:#c6a0f6&#34;&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;I don&amp;#39;t know the secret.&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;anotherValue&lt;/span&gt; = ProcessInfo.processInfo.environment[&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;ANOTHER&amp;#34;&lt;/span&gt;] {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(anotherValue)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    } &lt;span style=&#34;color:#c6a0f6&#34;&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;I don&amp;#39;t know the other secret.&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;catch&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;error&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;) &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//handle or silence the error here&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;posting-hello&#34;&gt;Posting Hello&lt;/h3&gt;
&lt;p&gt;Getting just a simple status to post meant not simply adding URLQueryItems to the endpoint but doing &amp;ldquo;URLEncoded&amp;rdquo; data and adding the token to the HTTP Header. Thankfully that is the &lt;code&gt;urlsession.upload()&lt;/code&gt; default.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//using async upload, see APing for manual body example.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;post_URLEncoded&lt;/span&gt;(baseUrl:URL, formData:&lt;span style=&#34;color:#91d7e3&#34;&gt;Dictionary&lt;/span&gt;&amp;lt;&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;, CustomStringConvertible&amp;gt;, withAuth:&lt;span style=&#34;color:#91d7e3&#34;&gt;Bool&lt;/span&gt; = &lt;span style=&#34;color:#f5a97f&#34;&gt;true&lt;/span&gt;) async &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; -&amp;gt; Data {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//cachePolicy: URLRequest.CachePolicy, timeoutInterval: TimeInterval&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;request&lt;/span&gt; = URLRequest(url: baseUrl)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        request.httpMethod = &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;POST&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; withAuth { &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; addAuth(request: &amp;amp;request) }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;dataToSend&lt;/span&gt; = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; URLEncoder.makeURLEncodedString(formItems: formData).data(using: .utf8)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//Uneeded b/c this appears to be the default.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//request.setValue(&amp;#34;application/x-www-form-urlencoded; charset=utf-8&amp;#34;, forHTTPHeaderField: &amp;#34;Content-Type&amp;#34;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; await requestService.postData(urlRequest: request, data: dataToSend!)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//using async upload, see APing for manual body example.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;post_URLEncoded&lt;/span&gt;(baseUrl:URL, dataToSend:Data, withAuth:&lt;span style=&#34;color:#91d7e3&#34;&gt;Bool&lt;/span&gt; = &lt;span style=&#34;color:#f5a97f&#34;&gt;true&lt;/span&gt;) async &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; -&amp;gt; Data {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//cachePolicy: URLRequest.CachePolicy, timeoutInterval: TimeInterval&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;request&lt;/span&gt; = URLRequest(url: baseUrl)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        request.httpMethod = &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;POST&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; withAuth { &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; addAuth(request: &amp;amp;request) }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; await requestService.postData(urlRequest: request, data: dataToSend)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Adding auth:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//In public extension on APIService where Self:Authorizable&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;addAuth&lt;/span&gt;(request: &lt;span style=&#34;color:#c6a0f6&#34;&gt;inout&lt;/span&gt; URLRequest) &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//print(self)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//might also consider checking validation. &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//print(&amp;#34;addAuth: hasValidToken \(self.hasValidToken)&amp;#34;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;auth&lt;/span&gt; = &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;.authentication {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; auth.addBearerToken(to:&amp;amp;request)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        } &lt;span style=&#34;color:#c6a0f6&#34;&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;throw&lt;/span&gt; AuthorizableError(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;No authorizations defined.&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//in Authentication&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;addBearerToken&lt;/span&gt;(to request: &lt;span style=&#34;color:#c6a0f6&#34;&gt;inout&lt;/span&gt; URLRequest) &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        request.setValue(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Bearer &lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; fetchToken&lt;span style=&#34;color:#a6da95&#34;&gt;())&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;, forHTTPHeaderField: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Authorization&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Over in request service:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;postData&lt;/span&gt;(urlRequest:URLRequest, data:Data) async &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; -&amp;gt; Data {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; (responseData, response) = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; await session.upload(&lt;span style=&#34;color:#c6a0f6&#34;&gt;for&lt;/span&gt;: urlRequest, from: data, delegate: &lt;span style=&#34;color:#f5a97f&#34;&gt;nil&lt;/span&gt;)        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;guard&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;httpResponse&lt;/span&gt; = response &lt;span style=&#34;color:#c6a0f6&#34;&gt;as&lt;/span&gt;? HTTPURLResponse &lt;span style=&#34;color:#c6a0f6&#34;&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(response)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;throw&lt;/span&gt; HTTPRequestServiceError(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Not an HTTP Response.&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;         &lt;span style=&#34;color:#c6a0f6&#34;&gt;guard&lt;/span&gt; (&lt;span style=&#34;color:#f5a97f&#34;&gt;200.&lt;/span&gt;..&lt;span style=&#34;color:#f5a97f&#34;&gt;299&lt;/span&gt;).&lt;span style=&#34;color:#91d7e3&#34;&gt;contains&lt;/span&gt;(httpResponse.statusCode)  &lt;span style=&#34;color:#c6a0f6&#34;&gt;else&lt;/span&gt;  {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;             &lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(response)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;             &lt;span style=&#34;color:#c6a0f6&#34;&gt;throw&lt;/span&gt; HTTPRequestServiceError(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Request Failed:&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;httpResponse.statusCode&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;, &lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;(&lt;/span&gt;describing:httpResponse.mimeType&lt;span style=&#34;color:#a6da95&#34;&gt;))&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;         }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; responseData
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Some encoding helpers.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;makeQueryItems&lt;/span&gt;(from itemToEncode:Encodable) -&amp;gt; [URLQueryItem] {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;encoder&lt;/span&gt; = JSONEncoder()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;encode&lt;/span&gt;&amp;lt;T&amp;gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; value: T) &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; -&amp;gt; [&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;: &lt;span style=&#34;color:#91d7e3&#34;&gt;Any&lt;/span&gt;] &lt;span style=&#34;color:#c6a0f6&#34;&gt;where&lt;/span&gt; T : Encodable {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;data&lt;/span&gt; = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; encoder.encode(value)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; JSONSerialization.jsonObject(with: data, options: .allowFragments) &lt;span style=&#34;color:#c6a0f6&#34;&gt;as&lt;/span&gt;! [&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;: &lt;span style=&#34;color:#91d7e3&#34;&gt;Any&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;guard&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;dictionary&lt;/span&gt; = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt;? encode(itemToEncode) &lt;span style=&#34;color:#c6a0f6&#34;&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//print(&amp;#34;got nothing&amp;#34;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; []
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;queries&lt;/span&gt;:[URLQueryItem] = []
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;for&lt;/span&gt; (key, value) &lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt; dictionary {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;stringValue&lt;/span&gt; = &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;value&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; stringValue == &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;(&lt;/span&gt;&lt;span style=&#34;color:#8aadf4&#34;&gt;\n&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;)&amp;#34;&lt;/span&gt; { stringValue = &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; stringValue.hasPrefix(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;(&amp;#34;&lt;/span&gt;) { stringValue = stringValue.trimmingCharacters(&lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt;: CharacterSet(charactersIn: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;()&amp;#34;&lt;/span&gt;)).removingCharacters(&lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt;: .whitespacesAndNewlines)}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//print(stringValue)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#c6a0f6&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;!&lt;/span&gt;stringValue.&lt;span style=&#34;color:#91d7e3&#34;&gt;isEmpty&lt;/span&gt;  {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                queries.append(URLQueryItem(name: key, value: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;stringValue&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; queries
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;makeURLEncodedString&lt;/span&gt;(queryItems:[URLQueryItem]) &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; -&amp;gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        queryItems.&lt;span style=&#34;color:#91d7e3&#34;&gt;map&lt;/span&gt;(urlEncode).joined(separator: &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&amp;amp;&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;private&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;urlEncode&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; queryItem: URLQueryItem) -&amp;gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;name&lt;/span&gt; = urlEncode(queryItem.name)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;value&lt;/span&gt; = urlEncode(queryItem.value ?? &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;name&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;\(&lt;/span&gt;value&lt;span style=&#34;color:#a6da95&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;private&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;urlEncode&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; string: &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;) -&amp;gt; &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        string.addingPercentEncoding(withAllowedCharacters: CharacterSet.alphanumerics) ?? &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;finally-actually-posting-on-mastodon&#34;&gt;Finally&amp;hellip; actually Posting on Mastodon&lt;/h3&gt;
&lt;p&gt;And now we have the very short &amp;ldquo;Hello World&amp;rdquo; posting function&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;newPost&lt;/span&gt;(message:&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;) async &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;path&lt;/span&gt;:&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;? = actions[&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;new_status&amp;#34;&lt;/span&gt;]?.endPointPath
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;url&lt;/span&gt; = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; urlFrom(path: path!, prependBasePath: &lt;span style=&#34;color:#f5a97f&#34;&gt;true&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;returnData&lt;/span&gt; = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; await post_URLEncoded(baseUrl:url, formData:[&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;status&amp;#34;&lt;/span&gt;:message], withAuth:&lt;span style=&#34;color:#f5a97f&#34;&gt;true&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;(data: returnData, encoding: .utf8)&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;!&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This was a a bunch to get done, and I STILL can&amp;rsquo;t post an image!&lt;/p&gt;
</description>
    </item>
    
    
    
    <item>
      <title>Getting scripty</title>
      <link>https://whynotestflight.com/excuses/getting-scripty/</link>
      <pubDate>Sat, 04 Feb 2023 00:00:00 +0000</pubDate>
      
      <guid>https://whynotestflight.com/excuses/getting-scripty/</guid>
      <description>&lt;p&gt;So as part of last month I was using Python to create a Static Site Generator. I wanted to see if I could use swift for scripting, too. The answer is a qualified yes.&lt;/p&gt;
&lt;p&gt;See the &lt;a href=&#34;https://github.com/carlynorama/swift-scripting/&#34;&gt;swift-scripting&lt;/a&gt; repo for more details&lt;/p&gt;
&lt;p&gt;Yes, one can pretty easily knock out a script&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;#&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;!/&lt;/span&gt;usr&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;/&lt;/span&gt;bin&lt;span style=&#34;color:#91d7e3;font-weight:bold&#34;&gt;/&lt;/span&gt;env swift
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//    chmod +x swift_hello &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//    ./swift_hello.swift apple banana kumquat&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;// Outputs&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//     Number of arguments: 3&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//     Arguments:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//     - apple&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//     - banana&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//     - kumquat&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//https://theswiftdev.com/how-to-build-better-command-line-apps-and-tools-using-swift/&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Hello, world!&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;/// the very first element is the current script&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;script&lt;/span&gt; = CommandLine.arguments[&lt;span style=&#34;color:#f5a97f&#34;&gt;0&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Script:&amp;#34;&lt;/span&gt;, script)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;/// you can get the input arguments by dropping the first element&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;inputArgs&lt;/span&gt; = CommandLine.arguments.&lt;span style=&#34;color:#91d7e3&#34;&gt;dropFirst&lt;/span&gt;()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Number of arguments:&amp;#34;&lt;/span&gt;, inputArgs.&lt;span style=&#34;color:#91d7e3&#34;&gt;count&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Arguments:&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;for&lt;/span&gt; arg &lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt; inputArgs {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;-&amp;#34;&lt;/span&gt;, arg)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;/// reading lines from the standard input&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Please enter your input:&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#c6a0f6&#34;&gt;guard&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;input&lt;/span&gt; = readLine(strippingNewline: &lt;span style=&#34;color:#f5a97f&#34;&gt;true&lt;/span&gt;) &lt;span style=&#34;color:#c6a0f6&#34;&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#91d7e3&#34;&gt;fatalError&lt;/span&gt;(&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;Missing input&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#91d7e3&#34;&gt;print&lt;/span&gt;(input)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Advantage over Python: C code can just be punked straight into these scripts, no questions asked.&lt;/p&gt;
&lt;p&gt;Disadvantage over Python: Swift can&amp;rsquo;t really do multi-file &amp;ldquo;scripts&amp;rdquo; as effortlessly since Swift is a compiled language, but if you don&amp;rsquo;t want to bother with making a package the following will get you an executable without much fuss.&lt;/p&gt;
&lt;p&gt;One just uses the code from one file in another other files, no import statement needed. No header file. Although tools like VScode and Xcode won&amp;rsquo;t really be able to help out with code completion.&lt;/p&gt;
&lt;p&gt;When you have what you want it&amp;rsquo;s compile time:&lt;/p&gt;
&lt;p&gt;compile with: &lt;code&gt;swiftc *swift -o myappname&lt;/code&gt; where&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;swiftx&lt;/code&gt;: swift complier&lt;/li&gt;
&lt;li&gt;&lt;code&gt;*swift&lt;/code&gt;: include all files with names that end in &lt;code&gt;swift&lt;/code&gt; (this directory non-recursive but can point anywhere)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;-o myappname&lt;/code&gt;: &lt;code&gt;-o&lt;/code&gt; means that you are about to give the compiler the name wanted for the output.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;for more info &lt;code&gt;swiftc --help&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;or also &lt;code&gt;swiftc `find . -name &amp;quot;*.swift&amp;quot; -maxdepth 1` -o myappname&lt;/code&gt; where&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;.&lt;/code&gt;: current directory&lt;/li&gt;
&lt;li&gt;&lt;code&gt;maxdepth&lt;/code&gt;: how far down the file tree to look&lt;/li&gt;
&lt;li&gt;FYI: using backticks in a shell command is spawning a subshell, e.g. &lt;code&gt;ls -l `which python3`&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;the result will be a new item, an executable, in the file directory which can then be run via the command line with &lt;code&gt;./myappname&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;otool -L ./myappname&lt;/code&gt; will print to the console all the libraries that the Linker believes are used of your app. The &lt;code&gt;swiftc&lt;/code&gt; compile by default is a dynamic compile  (vs static) so this is a lookup table. The files have not been copied into the app directory. &lt;code&gt;swiftc -static-executable&lt;/code&gt; when compiling will do a static compile instead (if compiling for a non-Apple platform).&lt;/p&gt;
&lt;p&gt;NOTE:&lt;a href=&#34;https://github.com/carlynorama/tipsy-robot-swift&#34;&gt;tipsy-robot-swift&lt;/a&gt; i.e. the following weeks post has info on using a package.&lt;/p&gt;
&lt;h1 id=&#34;january-wrap-up-tasks&#34;&gt;January Wrap Up Tasks&lt;/h1&gt;
&lt;p&gt;Wrapped up the Nature of Code project doing things like&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Adding CSS to make it more readable: &lt;a href=&#34;https://accessibility.huit.harvard.edu/design-readability&#34;&gt;https://accessibility.huit.harvard.edu/design-readability&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Cleaned &lt;a href=&#34;https://github.com/carlynorama/small-ssg&#34;&gt;small-ssg&lt;/a&gt; to make Day Index titles as well as split up the generation of the embeds and the nav links in the templates.&lt;/li&gt;
&lt;li&gt;Posted and example to the &lt;a href=&#34;https://www.thecodingtrain.com&#34;&gt;Coding Train&lt;/a&gt; website - &lt;a href=&#34;https://thecodingtrain.com/tracks/the-nature-of-code-2/noc/5-autonomous-agents/6-scalar-projection&#34;&gt;Scalar Projection&lt;/a&gt; I had to strip out my Vector Library but seemed worth it.&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id=&#34;site-meta&#34;&gt;Site Meta&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;Post files were all in the top level on the public website, which was cluttered so I fixed it: &lt;a href=&#34;https://github.com/wowchemy/wowchemy-hugo-themes/issues/356&#34;&gt;https://github.com/wowchemy/wowchemy-hugo-themes/issues/356&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Did some back fill to at least link to repos I was working on in a given week.&lt;/li&gt;
&lt;/ul&gt;
</description>
    </item>
    
    
    
    <item>
      <title>Ran out of NoC v2 playlist? But wait, there&#39;s more!</title>
      <link>https://whynotestflight.com/excuses/ran-out-of-noc-v2-playlist-but-wait-theres-more/</link>
      <pubDate>Sat, 28 Jan 2023 00:00:00 +0000</pubDate>
      
      <guid>https://whynotestflight.com/excuses/ran-out-of-noc-v2-playlist-but-wait-theres-more/</guid>
      <description>&lt;p&gt;The &lt;a href=&#34;https://www.youtube.com/playlist?list=PLRqwX-V7Uu6ZV4yEcW3uDwOgGXKUUsPOM&#34;&gt;Nature of Code 2 Playlist&lt;/a&gt; ends after Chapter 6, but the book has a few more chapters after that. Shiffman has posted plenty of relevant material even if it&amp;rsquo;s not in that playlist though so no reason to stop now!&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Jan 22. &lt;a href=&#34;https://carlynorama.github.io/2023January-30DaysNatureOfCode/22-scalar-projection&#34;&gt;22-scalar-projection&lt;/a&gt;: Scalar projection visualization and some Vector class refactoring. Breaking changes.&lt;/li&gt;
&lt;li&gt;Jan 23. &lt;a href=&#34;https://carlynorama.github.io/2023January-30DaysNatureOfCode/23-path-following&#34;&gt;23-path-following&lt;/a&gt;: Path following and hue table and triangle bounds detection, Oh my!&lt;/li&gt;
&lt;li&gt;Jan 24. &lt;a href=&#34;https://carlynorama.github.io/2023January-30DaysNatureOfCode/24-cellular-automata&#34;&gt;24-cellular-automata&lt;/a&gt;: No more videos in the Nature of Code 2 playlist, start Chapter 7 anyway following V1.&lt;/li&gt;
&lt;li&gt;Jan 25. &lt;a href=&#34;https://carlynorama.github.io/2023January-30DaysNatureOfCode/25-intro-fractals&#34;&gt;25-intro-fractals&lt;/a&gt;: Part one of Chapter 8, basic recursion and start of fractals. Mostly just copying the processing -&amp;gt; p5js / TypeScript.&lt;/li&gt;
&lt;li&gt;Jan 26. &lt;a href=&#34;https://carlynorama.github.io/2023January-30DaysNatureOfCode/26-branching-fractals&#34;&gt;26-branching-fractals&lt;/a&gt;: Simple Trees and an L-System&lt;/li&gt;
&lt;li&gt;Jan 27. &lt;a href=&#34;https://carlynorama.github.io/2023January-30DaysNatureOfCode/27-selection&#34;&gt;27-selection&lt;/a&gt;: Before going elbow deep into chapter 9, understanding Rejection Sampling.&lt;/li&gt;
&lt;li&gt;Jan 28. &lt;a href=&#34;https://carlynorama.github.io/2023January-30DaysNatureOfCode/28-genetic-algorithms&#34;&gt;28-genetic-algorithms&lt;/a&gt;: Getting the &amp;ldquo;To be or not to be.&amp;rdquo; example working, trying to add a &amp;ldquo;novelty bonus.&amp;rdquo;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;See it all at the &lt;a href=&#34;https://github.com/carlynorama/2023January-30DaysNatureOfCode&#34;&gt;January 2023 Repo&lt;/a&gt; or &lt;a href=&#34;https://carlynorama.github.io/2023January-30DaysNatureOfCode/&#34;&gt;the GHPages site&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The things I had a lot of fun exploring were actually sub-problems, &lt;a href=&#34;https://carlynorama.github.io/2023January-30DaysNatureOfCode/22-scalar-projection&#34;&gt;scalar projection&lt;/a&gt;, &lt;a href=&#34;https://carlynorama.github.io/2023January-30DaysNatureOfCode/27-selection&#34;&gt;rejection sampling&lt;/a&gt; and &lt;a href=&#34;https://math.stackexchange.com/a/4624564&#34;&gt;triangle hit detection&lt;/a&gt;&lt;/p&gt;
&lt;h3 id=&#34;misc-non-nature-of-code-links&#34;&gt;Misc Non-Nature of Code links&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Computerphile episode on genetic algorithms: &lt;a href=&#34;https://www.youtube.com/watch?v=MacVqujSXWE&#34;&gt;https://www.youtube.com/watch?v=MacVqujSXWE&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;MIT 6.034 Lecture on the same: &lt;a href=&#34;https://www.youtube.com/watch?v=kHyNqSnzP8Y&#34;&gt;https://www.youtube.com/watch?v=kHyNqSnzP8Y&lt;/a&gt;, I liked the phrase &amp;ldquo;simulated annealing&amp;rdquo;&lt;/li&gt;
&lt;li&gt;3Blue1Brown, Linear Algebra &lt;a href=&#34;https://www.3blue1brown.com/topics/linear-algebra&#34;&gt;https://www.3blue1brown.com/topics/linear-algebra&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;script src=&#34;https://cdn.jsdelivr.net/npm/p5@1.5.0/lib/p5.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;follower.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;path.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;vector.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;vehicle.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;controller.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;sketch.js&#34;&gt;&lt;/script&gt;
</description>
    </item>
    
    
    
    <item>
      <title>hunh... I resemble that boid...</title>
      <link>https://whynotestflight.com/excuses/hunh...-i-resemble-that-boid.../</link>
      <pubDate>Sat, 21 Jan 2023 00:00:00 +0000</pubDate>
      
      <guid>https://whynotestflight.com/excuses/hunh...-i-resemble-that-boid.../</guid>
      <description>&lt;p&gt;Continuing with &lt;a href=&#34;https://www.youtube.com/playlist?list=PLRqwX-V7Uu6ZV4yEcW3uDwOgGXKUUsPOM&#34;&gt;Nature of Code 2 Playlist&lt;/a&gt;.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Jan 15. &lt;a href=&#34;https://github.com/carlynorama/2023January-30DaysNatureOfCode/15-oscillation&#34;&gt;15-oscillation&lt;/a&gt;: Oscillation from Chapter 3 videos 5, 6 and 7&lt;/li&gt;
&lt;li&gt;Jan 16. &lt;a href=&#34;https://github.com/carlynorama/2023January-30DaysNatureOfCode/16-swing-time&#34;&gt;16-swing-time&lt;/a&gt;: Pendulums via Chapter 3 section&amp;rsquo;s reference to Coding Challenge #159&lt;/li&gt;
&lt;li&gt;Jan 17. &lt;a href=&#34;dhttps://github.com/carlynorama/2023January-30DaysNatureOfCode/17-springs&#34;&gt;17-springs&lt;/a&gt;: Simple spring systems referencing Coding Challenge #160&lt;/li&gt;
&lt;li&gt;Jan 18. &lt;a href=&#34;https://github.com/carlynorama/2023January-30DaysNatureOfCode/18-simple-particle-system&#34;&gt;18-simple-particle-system&lt;/a&gt;: Starting Chapter 4 with some simple particle system work, and also some website meta. Check out the new files in &lt;code&gt;site-gen&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Jan 19. &lt;a href=&#34;https://github.com/carlynorama/2023January-30DaysNatureOfCode/19-recordable-particles&#34;&gt;19-recordable-particles&lt;/a&gt;: Wrapping up Chapter 4 with refactored particle. Also some improvements to &lt;code&gt;controller.ts&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Jan 20. &lt;a href=&#34;https://github.com/carlynorama/2023January-30DaysNatureOfCode/20-simple-vehicles&#34;&gt;20-simple-vehicles&lt;/a&gt;: Start Chapter 5, Autonomous Agents&lt;/li&gt;
&lt;li&gt;Jan 21. &lt;a href=&#34;https://github.com/carlynorama/2023January-30DaysNatureOfCode/21-wanderer&#34;&gt;21-wanderer&lt;/a&gt;: The Wanderer&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;See it all at the &lt;a href=&#34;https://github.com/carlynorama/2023January-30DaysNatureOfCode&#34;&gt;January 2023 Repo&lt;/a&gt; or &lt;a href=&#34;https://carlynorama.github.io/2023January-30DaysNatureOfCode/&#34;&gt;the GHPages site&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The week started with oscillations and ended up using oscillations to create random movement. The reference in the post title, &lt;a href=&#34;https://en.wikipedia.org/wiki/Boids&#34;&gt;boids&lt;/a&gt;, is from the Craig Reynolds paper below.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Paper: Steering Behaviors For Autonomous Characters by Craig Reynolds, &lt;a href=&#34;https://www.red3d.com/cwr/steer/&#34;&gt;https://www.red3d.com/cwr/steer/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Book: Vehicles: Experiments in Synthetic Psychology by Valentino Braitenberg, &lt;a href=&#34;https://mitpress.mit.edu/9780262521123/&#34;&gt;https://mitpress.mit.edu/9780262521123/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Nature of Code Chapter: &lt;a href=&#34;https://natureofcode.com/book/chapter-6-autonomous-agents/&#34;&gt;https://natureofcode.com/book/chapter-6-autonomous-agents/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Up until this week various noise functions provided the naturalizing component. This week shows how recursive/stacked/nested functions can bring the chaos.&lt;/p&gt;
&lt;script src=&#34;https://cdn.jsdelivr.net/npm/p5@1.5.0/lib/p5.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;controller.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;vector.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;vehicle.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;wanderer.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;sketch.js&#34;&gt;&lt;/script&gt;
</description>
    </item>
    
    
    
    <item>
      <title>oooOO how does TypeScript work?</title>
      <link>https://whynotestflight.com/excuses/ooooo-how-does-typescript-work/</link>
      <pubDate>Sat, 14 Jan 2023 00:00:00 +0000</pubDate>
      
      <guid>https://whynotestflight.com/excuses/ooooo-how-does-typescript-work/</guid>
      <description>&lt;p&gt;Having lots of fun with the &lt;a href=&#34;https://www.youtube.com/playlist?list=PLRqwX-V7Uu6ZV4yEcW3uDwOgGXKUUsPOM&#34;&gt;Nature of Code 2 Playlist&lt;/a&gt;. I&amp;rsquo;ve been binging the regular videos and dwelling on the Coding Challenge recommendations. From the 7th to the 14th I&amp;rsquo;ve gotten through:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://carlynorama.github.io/2023January-30DaysNatureOfCode/&#34;&gt;wrapping up the quadtree&lt;/a&gt; for now.&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/carlynorama/2023January-30DaysNatureOfCode/blob/main/moving-to-typescript.md&#34;&gt;Moving to TypeScript&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Making &lt;a href=&#34;https://carlynorama.github.io/2023January-30DaysNatureOfCode/13-more-noise-loops/&#34;&gt;recordable Perlin noise loops&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Trying out OpenSimplex noise which led me to investigate &lt;a href=&#34;https://github.com/carlynorama/open-simplex-noise-for-web-js&#34;&gt;recompiling a node.js TypeScript library&lt;/a&gt; for web use.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;See it all at the &lt;a href=&#34;https://github.com/carlynorama/2023January-30DaysNatureOfCode&#34;&gt;January 2023 Repo&lt;/a&gt; or &lt;a href=&#34;https://carlynorama.github.io/2023January-30DaysNatureOfCode/&#34;&gt;the GHPages site&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;TypeScript may seem like over kill, but troubleshooting the loosey goosey JavaScript with only &lt;code&gt;console.log&lt;/code&gt; in your tool set SUCKS. Now that I have the TypeScript/VSCode setup working they catch a lot of the hard to suss out errors before I even make it to the browser to look at the progress. My strongly-typed-complied-soul feels a lot more comfortable.&lt;/p&gt;
&lt;script src=&#34;https://cdn.jsdelivr.net/npm/p5@1.5.0/lib/p5.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;controller.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;sketch.js&#34;&gt;&lt;/script&gt;
&lt;h2 id=&#34;meta&#34;&gt;META&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;What happens when I put script tags in here??? THEY WORK!!&lt;/li&gt;
&lt;/ul&gt;
</description>
    </item>
    
    
    
    <item>
      <title>Genuary Adjacent</title>
      <link>https://whynotestflight.com/excuses/genuary-adjacent/</link>
      <pubDate>Sat, 07 Jan 2023 00:00:00 +0000</pubDate>
      
      <guid>https://whynotestflight.com/excuses/genuary-adjacent/</guid>
      <description>&lt;p&gt;I had so much fun with &lt;a href=&#34;https://adventofcode.com&#34;&gt;Advent of Code&lt;/a&gt; that I thought I would check out &lt;a href=&#34;https://genuary.art&#34;&gt;Genuary&lt;/a&gt;. My reasoning was is that The App is really a creative coding exercise, and I haven&amp;rsquo;t made screen based art in long while. I&amp;rsquo;ve spent so much time on the infrastructure partially because I&amp;rsquo;ve been avoiding sitting with the visuals.&lt;/p&gt;
&lt;p&gt;I didn&amp;rsquo;t think that Genuary was going to get me where I need to go, so instead I&amp;rsquo;ve chosen to follow along with Daniel Shiffman&amp;rsquo;s Nature of Code 2 playlist.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Nature of Code 2 Playlist: &lt;a href=&#34;https://www.youtube.com/playlist?list=PLRqwX-V7Uu6ZV4yEcW3uDwOgGXKUUsPOM&#34;&gt;https://www.youtube.com/playlist?list=PLRqwX-V7Uu6ZV4yEcW3uDwOgGXKUUsPOM&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;NoC 1: &lt;a href=&#34;https://natureofcode.com/&#34;&gt;https://natureofcode.com/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;One way to do this would be the use the fabulous editors:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://p5js.org&#34;&gt;https://p5js.org&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://openprocessing.org/&#34;&gt;https://openprocessing.org/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;But instead I decided to gather it all into a unified &lt;a href=&#34;https://github.com/carlynorama/2023January-30DaysNatureOfCode&#34;&gt;January 2023 Repo&lt;/a&gt; which is published to GitHub Pages: &lt;a href=&#34;https://carlynorama.github.io/2023January-30DaysNatureOfCode/&#34;&gt;https://carlynorama.github.io/2023January-30DaysNatureOfCode/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Hilariously I&amp;rsquo;ve spend most of the time not making things that are about the looks, but rebuilding CGRect features in Javascript in order to create Quadtree representations&amp;hellip; so I may be using p5js&amp;hellip; but let&amp;rsquo;s face it&amp;hellip; it is still me doing it.&lt;/p&gt;
&lt;p&gt;The next week will be about combining p5js with TypeScript because I SORELY miss Swift.&lt;/p&gt;
&lt;h2 id=&#34;misc-other-resources&#34;&gt;Misc Other Resources&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://www.youtube.com/@TheCodingTrain&#34;&gt;https://www.youtube.com/@TheCodingTrain&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://thecodingtrain.com&#34;&gt;https://thecodingtrain.com&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://shiffman.net/&#34;&gt;https://shiffman.net/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/nature-of-code&#34;&gt;https://github.com/nature-of-code&lt;/a&gt; &amp;lt;- includes syllabus for course taught at NYU/ITP&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;meta&#34;&gt;META&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;I have a script to push this site to my server now: &lt;a href=&#34;https://github.com/carlynorama/myutils/blob/main/movers/pushLive.sh&#34;&gt;https://github.com/carlynorama/myutils/blob/main/movers/pushLive.sh&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Some fun helper files for the p5js site &lt;a href=&#34;https://github.com/carlynorama/2023January-30DaysNatureOfCode/tree/main/site-gen&#34;&gt;https://github.com/carlynorama/2023January-30DaysNatureOfCode/tree/main/site-gen&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;TODO: How to embed p5js into Hugo&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src=&#34;untitled-46_2.png&#34; alt=&#34;screenshot of the quadtree script - it shows white dots on a gray field with a red grid that has more density where there are more white dots.&#34;&gt;&lt;/p&gt;
</description>
    </item>
    
    
    
    <item>
      <title>New Years Eve and Math Vacation</title>
      <link>https://whynotestflight.com/excuses/new-years-eve-and-math-vacation/</link>
      <pubDate>Sat, 31 Dec 2022 00:00:00 +0000</pubDate>
      
      <guid>https://whynotestflight.com/excuses/new-years-eve-and-math-vacation/</guid>
      <description>&lt;p&gt;Advent of Code has made me realize that while I possibly actually am an okay programmer, that lack of official Computer Science training&amp;hellip; oof.&lt;/p&gt;
&lt;p&gt;Spent a &amp;ldquo;relaxing&amp;rdquo; week watching some of the videos for Mathematics of Computer Science on MIT Open CourseWare. It&amp;rsquo;s not a vacation FROM math. It&amp;rsquo;s a vacation TO math!&lt;/p&gt;
&lt;p&gt;There are two versions from different years with differing styles and slightly different order but they make for a nice compliment to each other:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://ocw.mit.edu/courses/6-042j-mathematics-for-computer-science-fall-2010/&#34;&gt;https://ocw.mit.edu/courses/6-042j-mathematics-for-computer-science-fall-2010/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://openlearninglibrary.mit.edu/courses/course-v1:OCW+6.042J+2T2019/course/&#34;&gt;https://openlearninglibrary.mit.edu/courses/course-v1:OCW+6.042J+2T2019/course/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;notes-to-self&#34;&gt;Notes to self&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Do read the recitation notes&lt;/li&gt;
&lt;li&gt;Do cross reference with content on other channels (This class is about PROOFS of things, not the things)&lt;/li&gt;
&lt;li&gt;No, you cannot do a 12 weeks of advanced math you&amp;rsquo;ve not done before class in 12 days. Nice thought though.&lt;/li&gt;
&lt;/ul&gt;
</description>
    </item>
    
    
    
    <item>
      <title>Oh hello Christmas...</title>
      <link>https://whynotestflight.com/excuses/oh-hello-christmas.../</link>
      <pubDate>Sat, 24 Dec 2022 00:00:00 +0000</pubDate>
      
      <guid>https://whynotestflight.com/excuses/oh-hello-christmas.../</guid>
      <description>&lt;p&gt;Got through Day 16 on the 18th&amp;hellip; but realized I had done NOTHING to prepare for the holidays. Tapped out to do deep character analysis of people instead of UInt8 strings and travel.&lt;/p&gt;
</description>
    </item>
    
    
    
    <item>
      <title>More advent of code...</title>
      <link>https://whynotestflight.com/excuses/more-advent-of-code.../</link>
      <pubDate>Sat, 17 Dec 2022 00:00:00 +0000</pubDate>
      
      <guid>https://whynotestflight.com/excuses/more-advent-of-code.../</guid>
      <description>&lt;p&gt;Still working on &lt;a href=&#34;https://adventofcode.com&#34;&gt;Advent of Code&lt;/a&gt;, haven&amp;rsquo;t finished day 16 yet&amp;hellip;&lt;/p&gt;
&lt;p&gt;Here&amp;rsquo;s a screen shot from the sand trap day.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;sandCourse_screenshot.png&#34; alt=&#34;a grid of hash marks and periods sketching out a sand obstacle course&#34;&gt;&lt;/p&gt;
</description>
    </item>
    
    
    
    <item>
      <title>What&#39;s this advent of code thing...</title>
      <link>https://whynotestflight.com/excuses/whats-this-advent-of-code-thing.../</link>
      <pubDate>Sat, 10 Dec 2022 19:36:36 -0800</pubDate>
      
      <guid>https://whynotestflight.com/excuses/whats-this-advent-of-code-thing.../</guid>
      <description>&lt;p&gt;Learned about &lt;a href=&#34;https://adventofcode.com&#34;&gt;Advent of Code&lt;/a&gt;, 25 challenges that are more than enough to keep me away from The App.&lt;/p&gt;
&lt;p&gt;Haven&amp;rsquo;t done a ton of text processing in Swift to date. I&amp;rsquo;ll update this post with some things I&amp;rsquo;ve learned later. (She did not.)&lt;/p&gt;
&lt;p&gt;The below image is from Day 9 and represents, in theory, the tail and of a rope as it swings through space. I suspect we are being pushed in the direction of writing snake.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;RopeTailPath.png&#34; alt=&#34;a light gray meandering line on a field of light gray dots laid out in a grid&#34;&gt;&lt;/p&gt;
</description>
    </item>
    
    
    
    <item>
      <title>--&gt; And of course there needs to be a blog...</title>
      <link>https://whynotestflight.com/excuses/--and-of-course-there-needs-to-be-a-blog.../</link>
      <pubDate>Fri, 02 Dec 2022 19:36:36 -0800</pubDate>
      
      <guid>https://whynotestflight.com/excuses/--and-of-course-there-needs-to-be-a-blog.../</guid>
      <description>&lt;p&gt;This is a place to keep the notes on what I&amp;rsquo;m doing.&lt;/p&gt;
&lt;p&gt;It is using &lt;a href=&#34;https://gohugo.io&#34;&gt;Hugo&lt;/a&gt;, so will have to learn GoLang a little bit too?&lt;/p&gt;
&lt;p&gt;All of this of course requires downloading and learning to use &lt;a href=&#34;https://code.visualstudio.com&#34;&gt;Visual Studio Code&lt;/a&gt;, too, since &lt;a href=&#34;https://atom.io&#34;&gt;Atom&lt;/a&gt; keeps telling me it&amp;rsquo;s going &lt;a href=&#34;https://github.blog/2022-06-08-sunsetting-atom/&#34;&gt;ride off into the sunset&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;It does not occur to me to use Xcode. It feels like bringing a sledgehammer to a tea party to use it on HTML and CSS type stuff, but that may simply be a question of habits.&lt;/p&gt;
</description>
    </item>
    
    
    
    <item>
      <title>Thanksgiving... time to brush-up on CSS!</title>
      <link>https://whynotestflight.com/excuses/thanksgiving...-time-to-brush-up-on-css/</link>
      <pubDate>Fri, 25 Nov 2022 00:00:00 +0000</pubDate>
      
      <guid>https://whynotestflight.com/excuses/thanksgiving...-time-to-brush-up-on-css/</guid>
      <description>&lt;p&gt;The app itself is going to need a website, and of course that needs to be made by hand. Time to relearn CSS!&lt;/p&gt;
&lt;p&gt;Started watching &lt;a href=&#34;https://www.udemy.com/course/css-the-complete-guide-incl-flexbox-grid-sass/learn/lecture/9591950?start=5#overview&#34;&gt;The Complete Guide 2023 (incl. Flexbox, Grid &amp;amp; Sass)&lt;/a&gt; on Udemy. It&amp;rsquo;s pretty good.&lt;/p&gt;
&lt;p&gt;Playing around with possible layouts for a new website for me. I&amp;rsquo;m not thrilled about having to use my real name in the app store, but am less thrilled about the idea of spinning up a whole company for a single small app.&lt;/p&gt;
&lt;p&gt;Of course need to make a website for CSS tests:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/carlynorama/CSSLayoutExamples&#34;&gt;repo&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://carlynorama.github.io/CSSLayoutExamples/&#34;&gt;repo as git-hub-pages demo&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</description>
    </item>
    
    
    
    <item>
      <title>A developer website needs a fun background image...</title>
      <link>https://whynotestflight.com/excuses/a-developer-website-needs-a-fun-background-image.../</link>
      <pubDate>Fri, 18 Nov 2022 00:00:00 +0000</pubDate>
      
      <guid>https://whynotestflight.com/excuses/a-developer-website-needs-a-fun-background-image.../</guid>
      <description>&lt;p&gt;&lt;img src=&#34;wallPaper_v1.png&#34; alt=&#34;A geometric image that uses triangles to greate a hexagonal basket weave look&#34;&gt;&lt;/p&gt;
&lt;p&gt;Inspired by a &lt;a href=&#34;https://www.hyggeandwest.com/products/quilt&#34;&gt;wallpaper pattern&lt;/a&gt;, using my Python based &lt;a href=&#34;https://github.com/carlynorama/graphpapers&#34;&gt;graphpaper generator&lt;/a&gt; to help make it more regular.  The plan is to replace it with something more dynamic soon, but this was a fun exercise.&lt;/p&gt;
</description>
    </item>
    
    
    
    <item>
      <title>Well the Instances need a page (Dictionary&#43;SwiftUI)</title>
      <link>https://whynotestflight.com/excuses/well-the-instances-need-a-page-dictionary-swiftui/</link>
      <pubDate>Fri, 11 Nov 2022 00:00:00 +0000</pubDate>
      
      <guid>https://whynotestflight.com/excuses/well-the-instances-need-a-page-dictionary-swiftui/</guid>
      <description>&lt;p&gt;Continued working on &lt;a href=&#34;https://github.com/carlynorama/ActivityPubExplorer/&#34;&gt;ActivityPubExplorer&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Also traveled.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;First order of business was prevent crashes when JSON was wobbly. This is on the list of things to refactor. It would be good to have it as a result type.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://github.com/carlynorama/ActivityPubExplorer/blob/c42039acc880c8e9da41a66f6e09325d556e04a2/ActivityPubExplorer/Generaic%20Services/RequestService%2BJSON.swift#L12&#34;&gt;https://github.com/carlynorama/ActivityPubExplorer/blob/c42039acc880c8e9da41a66f6e09325d556e04a2/ActivityPubExplorer/Generaic%20Services/RequestService%2BJSON.swift#L12&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Relevant Excerpt:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;Foundation&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;fileprivate &lt;span style=&#34;color:#ed8796&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;NullableObject&lt;/span&gt;&amp;lt;Base: Decodable&amp;gt;: Decodable {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;value&lt;/span&gt;: Base?
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;init&lt;/span&gt;(from decoder: Decoder) &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;do&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;container&lt;/span&gt; = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; decoder.singleValueContainer()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;.value = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; container.decode(Base.&lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        } &lt;span style=&#34;color:#c6a0f6&#34;&gt;catch&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;.value = &lt;span style=&#34;color:#f5a97f&#34;&gt;nil&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;extension&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;RequestService&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;fetchOptional&lt;/span&gt;&amp;lt;SomeDecodable: Decodable&amp;gt;(ofType:SomeDecodable.&lt;span style=&#34;color:#c6a0f6&#34;&gt;Type&lt;/span&gt;, from url:URL) async &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; -&amp;gt; SomeDecodable? {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;data&lt;/span&gt; = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; await httpFetch(from: url)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;result&lt;/span&gt; = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; JSONDecoder().decode(NullableObject&amp;lt;SomeDecodable&amp;gt;.&lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;, from: data)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; result.value
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8aadf4&#34;&gt;fetchCollectionOfOptionals&lt;/span&gt;&amp;lt;SomeDecodable: Decodable&amp;gt;(ofType:SomeDecodable.&lt;span style=&#34;color:#c6a0f6&#34;&gt;Type&lt;/span&gt;, from url:URL) async &lt;span style=&#34;color:#c6a0f6&#34;&gt;throws&lt;/span&gt; -&amp;gt; [SomeDecodable?] {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;data&lt;/span&gt; = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; await httpFetch(from: url)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;results&lt;/span&gt; = &lt;span style=&#34;color:#c6a0f6&#34;&gt;try&lt;/span&gt; JSONDecoder().decode([NullableObject&amp;lt;SomeDecodable&amp;gt;].&lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;, from: data)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; results.&lt;span style=&#34;color:#91d7e3&#34;&gt;map&lt;/span&gt; { &lt;span style=&#34;color:#f4dbd6&#34;&gt;$0&lt;/span&gt;.value }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Next things was to add instance profile pages.  Instance JSON was interesting because I&amp;rsquo;m not sure how regular the information will be instance to instance. That meant displaying JSON that&amp;rsquo;s was punked straight into a Dictionary just to see what was there.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://github.com/carlynorama/ActivityPubExplorer/blob/5da4591076eaef35576efc1e913e0b52013378d7/ActivityPubExplorer/StringDictionaryDisplay.swift&#34;&gt;https://github.com/carlynorama/ActivityPubExplorer/blob/5da4591076eaef35576efc1e913e0b52013378d7/ActivityPubExplorer/StringDictionaryDisplay.swift&lt;/a&gt;&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//  DictionaryDisplay.swift&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//  ActivityPubExplorer&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//  Created by Carlyn Maw on 11/9/22.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6e738d;font-style:italic&#34;&gt;//&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;SwiftUI&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;fileprivate &lt;span style=&#34;color:#ed8796&#34;&gt;extension&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;Dictionary&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;keyArray&lt;/span&gt;: [&lt;span style=&#34;color:#91d7e3&#34;&gt;Dictionary&lt;/span&gt;.Key] {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c6a0f6&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;.keys.&lt;span style=&#34;color:#91d7e3&#34;&gt;map&lt;/span&gt; { &lt;span style=&#34;color:#f4dbd6&#34;&gt;$0&lt;/span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;StringDictionaryDisplay&lt;/span&gt;: View {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;dictionary&lt;/span&gt;:&lt;span style=&#34;color:#91d7e3&#34;&gt;Dictionary&lt;/span&gt;&amp;lt;&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;, &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;keys&lt;/span&gt;:[&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;init&lt;/span&gt;(&lt;span style=&#34;color:#f5a97f&#34;&gt;_&lt;/span&gt; dictionary: &lt;span style=&#34;color:#91d7e3&#34;&gt;Dictionary&lt;/span&gt;&amp;lt;&lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;, &lt;span style=&#34;color:#91d7e3&#34;&gt;String&lt;/span&gt;&amp;gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;.dictionary = dictionary
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;.keys = dictionary.keyArray
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;body&lt;/span&gt;: some View {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        ForEach(keys, id:&lt;span style=&#34;color:#ed8796&#34;&gt;\&lt;/span&gt;.&lt;span style=&#34;color:#f5a97f&#34;&gt;self&lt;/span&gt;) { key &lt;span style=&#34;color:#c6a0f6&#34;&gt;in&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            LabeledContent(key, value: dictionary[key] ?? &lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;-&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed8796&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#eed49f&#34;&gt;StringDictionaryDisplay_Previews&lt;/span&gt;: PreviewProvider {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed8796&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#ed8796&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#f4dbd6&#34;&gt;previews&lt;/span&gt;: some View {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        StringDictionaryDisplay([&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;hello&amp;#34;&lt;/span&gt;:&lt;span style=&#34;color:#a6da95&#34;&gt;&amp;#34;world&amp;#34;&lt;/span&gt;])
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description>
    </item>
    
    
    
    <item>
      <title>Oh, maybe I should move to Mastodon.</title>
      <link>https://whynotestflight.com/excuses/oh-maybe-i-should-move-to-mastodon./</link>
      <pubDate>Sat, 29 Oct 2022 00:00:00 +0000</pubDate>
      
      <guid>https://whynotestflight.com/excuses/oh-maybe-i-should-move-to-mastodon./</guid>
      <description>&lt;p&gt;And if I was going to build an app, first it would need to connect to the internet.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://github.com/carlynorama/NetworkingExample&#34;&gt;https://github.com/carlynorama/NetworkingExample&lt;/a&gt;&lt;/p&gt;
</description>
    </item>
    
    
    
    <item>
      <title>Travel Interlude</title>
      <link>https://whynotestflight.com/excuses/travel-interlude/</link>
      <pubDate>Sat, 15 Oct 2022 00:00:00 +0000</pubDate>
      
      <guid>https://whynotestflight.com/excuses/travel-interlude/</guid>
      <description>&lt;p&gt;&lt;img src=&#34;20221014_a_lovely_lunch.jpeg&#34; alt=&#34;Image of a lovely lunch. A mixed salad in a white bowl. A tartine and a pizza both served on rustic cutting boards. In an outdoor setting with filtered dappled light.&#34;&gt;&lt;/p&gt;
</description>
    </item>
    
    
    
    <item>
      <title>So NavigationView... is not going to be helpful.</title>
      <link>https://whynotestflight.com/excuses/so-navigationview...-is-not-going-to-be-helpful./</link>
      <pubDate>Sat, 08 Oct 2022 00:00:00 +0000</pubDate>
      
      <guid>https://whynotestflight.com/excuses/so-navigationview...-is-not-going-to-be-helpful./</guid>
      <description>&lt;p&gt;I think its overkill for my two page app, and it does not behave in way that I like. Toooo opinionated, makes changes to the screen without user input. That said, how it interacts with the Layout system is pretty interesting.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://github.com/carlynorama/NavigationExplorer&#34;&gt;https://github.com/carlynorama/NavigationExplorer&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://stackoverflow.com/questions/73997331/passing-an-array-of-views-in-navigation-destination-in-swiftui-ios16/74001223#74001223&#34;&gt;https://stackoverflow.com/questions/73997331/passing-an-array-of-views-in-navigation-destination-in-swiftui-ios16/74001223#74001223&lt;/a&gt;&lt;/p&gt;
</description>
    </item>
    
    
    
    <item>
      <title>So NavigationView... would that helpful?</title>
      <link>https://whynotestflight.com/excuses/so-navigationview...-would-that-helpful/</link>
      <pubDate>Sat, 01 Oct 2022 00:00:00 +0000</pubDate>
      
      <guid>https://whynotestflight.com/excuses/so-navigationview...-would-that-helpful/</guid>
      <description>&lt;p&gt;Whelp&amp;hellip; it has some quirks&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://stackoverflow.com/questions/73941284/why-are-objects-still-in-memory-after-emptying-navigationstack-path/73954020#73954020&#34;&gt;https://stackoverflow.com/questions/73941284/why-are-objects-still-in-memory-after-emptying-navigationstack-path/73954020#73954020&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://github.com/carlynorama/NavigationExplorer&#34;&gt;https://github.com/carlynorama/NavigationExplorer&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Also, exploration of how to use AsyncStreams to get information out of classes and actors by wrapping @Published variables or replacing them all together.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://github.com/carlynorama/StreamPublisherTests&#34;&gt;https://github.com/carlynorama/StreamPublisherTests&lt;/a&gt;&lt;/p&gt;
</description>
    </item>
    
    
    
    <item>
      <title>Okay, lets try putting that all together</title>
      <link>https://whynotestflight.com/excuses/okay-lets-try-putting-that-all-together/</link>
      <pubDate>Sat, 24 Sep 2022 00:00:00 +0000</pubDate>
      
      <guid>https://whynotestflight.com/excuses/okay-lets-try-putting-that-all-together/</guid>
      <description>&lt;p&gt;Dummy app that uses a Service model to pass information around a weather service, and location service and a renderer.  Go figure.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://github.com/carlynorama/LocationExplorer&#34;&gt;https://github.com/carlynorama/LocationExplorer&lt;/a&gt;&lt;/p&gt;
</description>
    </item>
    
    
    
    <item>
      <title>But what if I should really be using Notifications?</title>
      <link>https://whynotestflight.com/excuses/but-what-if-i-should-really-be-using-notifications/</link>
      <pubDate>Sat, 17 Sep 2022 00:00:00 +0000</pubDate>
      
      <guid>https://whynotestflight.com/excuses/but-what-if-i-should-really-be-using-notifications/</guid>
      <description>&lt;p&gt;&lt;a href=&#34;https://github.com/carlynorama/NotificationTasks&#34;&gt;https://github.com/carlynorama/NotificationTasks&lt;/a&gt;&lt;/p&gt;
</description>
    </item>
    
    
    
    <item>
      <title>Time to swim up an @Published AsyncStream</title>
      <link>https://whynotestflight.com/excuses/time-to-swim-up-an-@published-asyncstream/</link>
      <pubDate>Sat, 10 Sep 2022 00:00:00 +0000</pubDate>
      
      <guid>https://whynotestflight.com/excuses/time-to-swim-up-an-@published-asyncstream/</guid>
      <description>&lt;p&gt;Watching an @Published var as a stream &amp;ldquo;for free&amp;rdquo;&amp;hellip; sort of.&lt;/p&gt;
&lt;p&gt;Gist: &lt;a href=&#34;https://gist.github.com/carlynorama/7532f59283bf1bddabe9932842752896&#34;&gt;https://gist.github.com/carlynorama/7532f59283bf1bddabe9932842752896&lt;/a&gt;
Project: &lt;a href=&#34;https://github.com/carlynorama/AsyncPublisherTests&#34;&gt;https://github.com/carlynorama/AsyncPublisherTests&lt;/a&gt;&lt;/p&gt;
</description>
    </item>
    
    
    
    <item>
      <title>Can I be of _Service_? (whomp whomp)</title>
      <link>https://whynotestflight.com/excuses/can-i-be-of-_service_-whomp-whomp/</link>
      <pubDate>Sat, 03 Sep 2022 00:00:00 +0000</pubDate>
      
      <guid>https://whynotestflight.com/excuses/can-i-be-of-_service_-whomp-whomp/</guid>
      <description>&lt;p&gt;So now the app has weather, and location and the renderer and they all have to talk to each other using test data in the prototype build and real data in the production build.&lt;/p&gt;
&lt;p&gt;Time to try out a Service Model.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://github.com/carlynorama/SimpleServiceModel&#34;&gt;https://github.com/carlynorama/SimpleServiceModel&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Cleaned up some of the layouts&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://github.com/carlynorama/LayoutTests/&#34;&gt;https://github.com/carlynorama/LayoutTests/&lt;/a&gt;&lt;/p&gt;
</description>
    </item>
    
    
    
    <item>
      <title>I know! I&#39;ll use Layouts!</title>
      <link>https://whynotestflight.com/excuses/i-know-ill-use-layouts/</link>
      <pubDate>Sat, 27 Aug 2022 00:00:00 +0000</pubDate>
      
      <guid>https://whynotestflight.com/excuses/i-know-ill-use-layouts/</guid>
      <description>&lt;p&gt;I just want a layout that will take up the amount of space I want it to? Is that so hard?&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://github.com/carlynorama/LayoutTests&#34;&gt;https://github.com/carlynorama/LayoutTests&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Yes.&lt;/p&gt;
</description>
    </item>
    
    
    
    <item>
      <title>Can I make the search dropdown feel niiiice?</title>
      <link>https://whynotestflight.com/excuses/can-i-make-the-search-dropdown-feel-niiiice/</link>
      <pubDate>Sat, 20 Aug 2022 00:00:00 +0000</pubDate>
      
      <guid>https://whynotestflight.com/excuses/can-i-make-the-search-dropdown-feel-niiiice/</guid>
      <description>&lt;p&gt;&lt;a href=&#34;https://github.com/carlynorama/AnimationTests&#34;&gt;https://github.com/carlynorama/AnimationTests&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Also create a stand alone package for handling location stuff so I can put it into the app.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://github.com/carlynorama/LocationServices&#34;&gt;https://github.com/carlynorama/LocationServices&lt;/a&gt;&lt;/p&gt;
</description>
    </item>
    
    
    
    <item>
      <title>What if people want to pick a location that isn&#39;t where they are?</title>
      <link>https://whynotestflight.com/excuses/what-if-people-want-to-pick-a-location-that-isnt-where-they-are/</link>
      <pubDate>Sat, 13 Aug 2022 00:00:00 +0000</pubDate>
      
      <guid>https://whynotestflight.com/excuses/what-if-people-want-to-pick-a-location-that-isnt-where-they-are/</guid>
      <description>&lt;p&gt;Test project for returning location search results: &lt;a href=&#34;https://github.com/carlynorama/LocationSearchExample/&#34;&gt;https://github.com/carlynorama/LocationSearchExample/&lt;/a&gt;&lt;/p&gt;
</description>
    </item>
    
    
    
    <item>
      <title>So I can have different builds without different projects?</title>
      <link>https://whynotestflight.com/excuses/so-i-can-have-different-builds-without-different-projects/</link>
      <pubDate>Sat, 06 Aug 2022 00:00:00 +0000</pubDate>
      
      <guid>https://whynotestflight.com/excuses/so-i-can-have-different-builds-without-different-projects/</guid>
      <description>&lt;p&gt;The app has a whole intense set up for prototyping the feel of the particles system that needs to be all stripped out for release into production.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ve never done anything like that so a bunch of the week was spent splitting the app into builds and trouble shooting various errors that came up. (Thanks to the flock, specifically Ed.)&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://developer.apple.com/documentation/xcode/customizing-the-build-schemes-for-a-project/&#34;&gt;https://developer.apple.com/documentation/xcode/customizing-the-build-schemes-for-a-project/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Also, helpful, wrote an Enum generated picker.&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;//
//  EnumPicker.swift
//  DataViewer
//
//  Created by carlynorama on 8/1/22.
//
import SwiftUI

protocol PickerSuppliable:CaseIterable, Hashable {
    var menuText:String { get }
}
fileprivate enum TestEnum:PickerSuppliable{
   // var id:TestEnum { self } //, does not infact need identifiable?
    
    case yes, no, maybe
    
    var menuText: String {
        switch self {
            
        case .yes:
            return &amp;#34;Yes&amp;#34;
        case .no:
            return &amp;#34;No&amp;#34;
        case .maybe:
            return &amp;#34;Maybe&amp;#34;
        }
    }
}
struct EnumPicker&amp;lt;E:PickerSuppliable&amp;gt;: View {
    let options:[E] = E.allCases as! [E]
    @Binding var value:E

    var body: some View {
        VStack {
            VStack {
                Picker(&amp;#34;Favorite Color&amp;#34;, selection: $value) {
                    ForEach(options, id: \.self) { option in
                        Text(option.menuText)
                    }
                }
            }
        }
    }
}
struct EnumPicker_Previews: PreviewProvider {
    static var previews: some View {
        VStack {
            EnumPicker&amp;lt;TestEnum&amp;gt;(value: .constant(.maybe))
            //Text(&amp;#34;Selected Item: \(value.menuText)&amp;#34;)
        }
    }
}
&lt;/code&gt;&lt;/pre&gt;</description>
    </item>
    
    
    
    <item>
      <title>If only I could use the settings I like to pick the curve...</title>
      <link>https://whynotestflight.com/excuses/if-only-i-could-use-the-settings-i-like-to-pick-the-curve.../</link>
      <pubDate>Sat, 30 Jul 2022 00:00:00 +0000</pubDate>
      
      <guid>https://whynotestflight.com/excuses/if-only-i-could-use-the-settings-i-like-to-pick-the-curve.../</guid>
      <description>&lt;p&gt;Initial commit to &lt;a href=&#34;https://github.com/carlynorama/DataHelper/&#34;&gt;DataHelper&lt;/a&gt; which takes in a paste of text data, makes a curve fit, and writes it to a chart.&lt;/p&gt;
</description>
    </item>
    
    
    
    <item>
      <title>You know, linear tapers are all wrong for this...</title>
      <link>https://whynotestflight.com/excuses/you-know-linear-tapers-are-all-wrong-for-this.../</link>
      <pubDate>Sat, 23 Jul 2022 00:00:00 +0000</pubDate>
      
      <guid>https://whynotestflight.com/excuses/you-know-linear-tapers-are-all-wrong-for-this.../</guid>
      <description>&lt;p&gt;&lt;a href=&#34;https://github.com/carlynorama/TaperSlider&#34;&gt;https://github.com/carlynorama/TaperSlider&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s you define a custom taper for a slider as long as that function has an inverse:&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://github.com/carlynorama/TaperSlider/blob/main/Sources/TaperSlider/FunctionPair.swift&#34;&gt;https://github.com/carlynorama/TaperSlider/blob/main/Sources/TaperSlider/FunctionPair.swift&lt;/a&gt;&lt;/p&gt;
</description>
    </item>
    
    
    
    <item>
      <title>But the particle shape&#39;s all wrong...</title>
      <link>https://whynotestflight.com/excuses/but-the-particle-shapes-all-wrong.../</link>
      <pubDate>Sat, 16 Jul 2022 00:00:00 +0000</pubDate>
      
      <guid>https://whynotestflight.com/excuses/but-the-particle-shapes-all-wrong.../</guid>
      <description>&lt;p&gt;New repos, the raw &lt;a href=&#34;https://github.com/carlynorama/PublicDrawingPractice&#34;&gt;Drawing Practice&lt;/a&gt; and the more cleaned up &lt;a href=&#34;https://github.com/carlynorama/ShapeExplorer&#34;&gt;Shape Explorer&lt;/a&gt;, in order to figure out how to draw custom paths in an app so my particle shape could be more organic.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;ScaledBezier&lt;/code&gt;:Shape&lt;/li&gt;
&lt;li&gt;&lt;code&gt;CustomShape&lt;/code&gt;:Shape&lt;/li&gt;
&lt;li&gt;&lt;code&gt;ScaledToFit&lt;/code&gt;:Shape&lt;/li&gt;
&lt;li&gt;&lt;code&gt;ScaledView&lt;/code&gt;:View&lt;/li&gt;
&lt;li&gt;&lt;code&gt;ScaledToAspect&lt;/code&gt;:Shape&lt;/li&gt;
&lt;li&gt;&lt;code&gt;ScaledToFill&lt;/code&gt;:Shape&lt;/li&gt;
&lt;li&gt;Misc custom &lt;code&gt;Shapes&lt;/code&gt; (&lt;code&gt;Diamond&lt;/code&gt;, &lt;code&gt;RightTriangle&lt;/code&gt;, etc.)&lt;/li&gt;
&lt;li&gt;Misc &lt;code&gt;UIBezier&lt;/code&gt; paths for testing&lt;/li&gt;
&lt;/ul&gt;
</description>
    </item>
    
    
    
    <item>
      <title>What I really need are some sliders...</title>
      <link>https://whynotestflight.com/excuses/what-i-really-need-are-some-sliders.../</link>
      <pubDate>Sat, 09 Jul 2022 00:00:00 +0000</pubDate>
      
      <guid>https://whynotestflight.com/excuses/what-i-really-need-are-some-sliders.../</guid>
      <description>&lt;p&gt;So in order to get the the movement of the particles JUUUUSSSSTTT RIGHT, you really need some sliders, which means&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A custom drawer view so you can show and hide them&lt;/li&gt;
&lt;li&gt;All the right hook ups to all the particle systems options&lt;/li&gt;
&lt;/ul&gt;
</description>
    </item>
    
    
    
    <item>
      <title>What if I made it different pieces?</title>
      <link>https://whynotestflight.com/excuses/what-if-i-made-it-different-pieces/</link>
      <pubDate>Sat, 02 Jul 2022 00:00:00 +0000</pubDate>
      
      <guid>https://whynotestflight.com/excuses/what-if-i-made-it-different-pieces/</guid>
      <description>&lt;p&gt;Two new repos:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/carlynorama/ParticleSystem&#34;&gt;Particle System&lt;/a&gt;: self evident name.&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/carlynorama/BlueSky&#34;&gt;BlueSky&lt;/a&gt; for handling weather API &amp;amp; fake weather data generation.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The whole week was packaging them up and then getting the app to work again with the packages.&lt;/p&gt;
</description>
    </item>
    
    
    
    <item>
      <title>Okay, well it works...</title>
      <link>https://whynotestflight.com/excuses/okay-well-it-works.../</link>
      <pubDate>Sat, 25 Jun 2022 00:00:00 +0000</pubDate>
      
      <guid>https://whynotestflight.com/excuses/okay-well-it-works.../</guid>
      <description>&lt;p&gt;A jest, and yet in the first week I had hello world on all the major aspects of the app:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;WeatherKit hello world&lt;/li&gt;
&lt;li&gt;Drawing to multiple aligned canvases, including a basic particle system.&lt;/li&gt;
&lt;li&gt;Getting weather data into a canvas&lt;/li&gt;
&lt;/ul&gt;
</description>
    </item>
    
    
    
    <item>
      <title>Maybe I&#39;ll write an app...</title>
      <link>https://whynotestflight.com/excuses/maybe-ill-write-an-app.../</link>
      <pubDate>Fri, 04 Feb 2022 00:00:00 +0000</pubDate>
      
      <guid>https://whynotestflight.com/excuses/maybe-ill-write-an-app.../</guid>
      <description>&lt;p&gt;First commit. It&amp;rsquo;s just an empty project for the day.&lt;/p&gt;
</description>
    </item>
    
    
    
    
    
    
  </channel>
</rss>
