<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Mathieu Kerjouan</title>
    <description>The latest articles on DEV Community by Mathieu Kerjouan (@niamtokik).</description>
    <link>https://dev.to/niamtokik</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1302415%2Ff02d4ee9-14d9-45ec-966a-6bb53e0e3240.jpeg</url>
      <title>DEV Community: Mathieu Kerjouan</title>
      <link>https://dev.to/niamtokik</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/niamtokik"/>
    <language>en</language>
    <item>
      <title>Q&amp;D: Android Device Information</title>
      <dc:creator>Mathieu Kerjouan</dc:creator>
      <pubDate>Wed, 14 Oct 2026 08:00:00 +0000</pubDate>
      <link>https://dev.to/niamtokik/qd-android-device-information-4mpb</link>
      <guid>https://dev.to/niamtokik/qd-android-device-information-4mpb</guid>
      <description>&lt;p&gt;It can be necessary, sometime, to collect device information, especially to identify a specific kind of device for debugging purpose, or to identify unique devices. In Dart/Flutter, one can install the &lt;a href="https://pub.dev/packages/device_info_plus" rel="noopener noreferrer"&gt;&lt;code&gt;device_info_plus&lt;/code&gt;&lt;/a&gt; package to have access to lot of informations regarding the device where the application is installed. Let have a quick look on this one.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="err"&gt;$&lt;/span&gt; &lt;span class="n"&gt;flutter&lt;/span&gt; &lt;span class="n"&gt;pub&lt;/span&gt; &lt;span class="n"&gt;add&lt;/span&gt; &lt;span class="n"&gt;device_info_plus&lt;/span&gt;
&lt;span class="n"&gt;Resolving&lt;/span&gt; &lt;span class="n"&gt;dependencies&lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt; 
&lt;span class="n"&gt;Downloading&lt;/span&gt; &lt;span class="n"&gt;packages&lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt; 
  &lt;span class="n"&gt;cupertino_icons&lt;/span&gt; &lt;span class="mf"&gt;1.0&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;9&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;2.0&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="n"&gt;available&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;device_info_plus&lt;/span&gt; &lt;span class="mf"&gt;13.3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;
&lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;device_info_plus_platform_interface&lt;/span&gt; &lt;span class="mf"&gt;8.1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;
&lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;ffi&lt;/span&gt; &lt;span class="mf"&gt;2.2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;
&lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;ffi_leak_tracker&lt;/span&gt; &lt;span class="mf"&gt;0.1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;
&lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;file&lt;/span&gt; &lt;span class="mf"&gt;7.0&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;
&lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;flutter_web_plugins&lt;/span&gt; &lt;span class="mf"&gt;0.0&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="n"&gt;from&lt;/span&gt; &lt;span class="n"&gt;sdk&lt;/span&gt; &lt;span class="n"&gt;flutter&lt;/span&gt;
  &lt;span class="n"&gt;material_color_utilities&lt;/span&gt; &lt;span class="mf"&gt;0.13&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;0.13&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="n"&gt;available&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;meta&lt;/span&gt; &lt;span class="mf"&gt;1.18&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;1.19&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="n"&gt;available&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;plugin_platform_interface&lt;/span&gt; &lt;span class="mf"&gt;2.1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;
  &lt;span class="n"&gt;test_api&lt;/span&gt; &lt;span class="mf"&gt;0.7&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;12&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;0.7&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;15&lt;/span&gt; &lt;span class="n"&gt;available&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;vector_math&lt;/span&gt; &lt;span class="mf"&gt;2.4&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;2.4&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt; &lt;span class="n"&gt;available&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;web&lt;/span&gt; &lt;span class="mf"&gt;1.1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;
&lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;win32&lt;/span&gt; &lt;span class="mf"&gt;6.4&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;
&lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;win32_registry&lt;/span&gt; &lt;span class="mf"&gt;3.0&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;
&lt;span class="n"&gt;Changed&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt; &lt;span class="n"&gt;dependencies&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;
&lt;span class="mi"&gt;5&lt;/span&gt; &lt;span class="n"&gt;packages&lt;/span&gt; &lt;span class="n"&gt;have&lt;/span&gt; &lt;span class="n"&gt;newer&lt;/span&gt; &lt;span class="n"&gt;versions&lt;/span&gt; &lt;span class="n"&gt;incompatible&lt;/span&gt; &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;dependency&lt;/span&gt; &lt;span class="n"&gt;constraints&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
&lt;span class="n"&gt;Try&lt;/span&gt; &lt;span class="err"&gt;`&lt;/span&gt;&lt;span class="n"&gt;flutter&lt;/span&gt; &lt;span class="n"&gt;pub&lt;/span&gt; &lt;span class="n"&gt;outdated&lt;/span&gt;&lt;span class="err"&gt;`&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;more&lt;/span&gt; &lt;span class="n"&gt;information&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The first step is to import the &lt;code&gt;device_info_plus&lt;/code&gt; package in your code.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="s"&gt;'package:device_info_plus/device_info_plus.dart'&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;One can extract only a small subset of all device information available, for example, to extract the device &lt;a href="https://pub.dev/documentation/device_info_plus/latest/device_info_plus/AndroidDeviceInfo/id.html" rel="noopener noreferrer"&gt;&lt;code&gt;id&lt;/code&gt;&lt;/a&gt;, the &lt;a href="https://pub.dev/documentation/device_info_plus/latest/device_info_plus/AndroidDeviceInfo/id.html" rel="noopener noreferrer"&gt;&lt;code&gt;id&lt;/code&gt;&lt;/a&gt; property can be retrieved and returned.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="n"&gt;Future&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;String&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;getDeviceId&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;DeviceInfoPlugin&lt;/span&gt; &lt;span class="n"&gt;deviceInfoPlugin&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;DeviceInfoPlugin&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="kt"&gt;String&lt;/span&gt; &lt;span class="n"&gt;deviceInfo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;deviceInfoPlugin&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;deviceInfo&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;deviceInfo&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If more information about a device is required, one can extract all of them as a &lt;code&gt;Map&amp;lt;String, dynamic&amp;gt;&lt;/code&gt; using the &lt;a href="https://pub.dev/documentation/device_info_plus/latest/device_info_plus/BaseDeviceInfo/data.html" rel="noopener noreferrer"&gt;&lt;code&gt;data&lt;/code&gt;&lt;/a&gt; property.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="n"&gt;Future&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;Map&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kd"&gt;dynamic&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;getDeviceInfoMap&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;DeviceInfoPlugin&lt;/span&gt; &lt;span class="n"&gt;deviceInfoPlugin&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;DeviceInfoPlugin&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="n"&gt;BaseDeviceInfo&lt;/span&gt; &lt;span class="n"&gt;deviceInfo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;deviceInfoPlugin&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;deviceInfo&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;deviceInfo&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;data&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Some information are only available on a specific kind of device (e.g. iOS, Android, Browser). If the application has been developed with portability in mind, it can also be a good idea to extract device's information based on the architecture/platform.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="n"&gt;Future&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;Map&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kd"&gt;dynamic&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;getAndroidDeviceInfoMap&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;DeviceInfoPlugin&lt;/span&gt; &lt;span class="n"&gt;deviceInfoPlugin&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;DeviceInfoPlugin&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="n"&gt;AndroidDeviceInfo&lt;/span&gt; &lt;span class="n"&gt;deviceInfo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;deviceInfoPlugin&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;androidInfo&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;deviceInfo&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;data&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here an example of the data extracted on an Android emulator:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;I/flutter ( 3959): physicalRamSize: 2472
I/flutter ( 3959): type: user
I/flutter ( 3959): manufacturer: Google
I/flutter ( 3959): freeDiskSize: 464072704
I/flutter ( 3959): bootloader: unknown
I/flutter ( 3959): fingerprint: google/sdk_gphone64_x86_64/emu64xa:16/BE2A.250530.026.D1/13818094:user/release-keys
I/flutter ( 3959): host: e8e8f3751cda
I/flutter ( 3959): isLowRamDevice: false
I/flutter ( 3959): model: sdk_gphone64_x86_64
I/flutter ( 3959): id: BE2A.250530.026.D1
I/flutter ( 3959): brand: google
I/flutter ( 3959): hardware: ranchu
I/flutter ( 3959): product: sdk_gphone64_x86_64
I/flutter ( 3959): totalDiskSize: 6228115456
I/flutter ( 3959): supportedAbis: [x86_64, arm64-v8a]
I/flutter ( 3959): supported32BitAbis: []
I/flutter ( 3959): display: BE2A.250530.026.D1
I/flutter ( 3959): isPhysicalDevice: false
I/flutter ( 3959): version: {baseOS: , securityPatch: 2025-07-05, sdkInt: 36, release: 16, codename: REL, previewSdkInt: 0, incremental: 13818094}
I/flutter ( 3959): systemFeatures: [android.hardware.sensor.proximity, android.software.adoptable_storage, android.hardware.sensor.accelerometer, android.software.controls, android.hardware.faketouch, android.software.telecom, android.hardware.telephony.subscription, android.hardware.reboot_escrow, android.hardware.telephony.data, android.software.backup, android.hardware.touchscreen, android.hardware.touchscreen.multitouch, android.software.erofs, android.software.print, android.software.activities_on_secondary_displays, android.software.device_lock, android.software.voice_recognizers, android.software.picture_in_picture, android.hardware.fingerprint, android.hardware.sensor.gyroscope, com.google.android.feature.PERSONAL_SAFETY, android.software.vulkan.deqp.level, android.software.cant_save_state, android.hardware.security.model.compatible, android.hardware.telephony.messaging, android.hardware.telephony.calling, android.hardware.sensor.relative_humidity, android.hardware.bluetooth, android.software.window_magnification, andr
I/flutter ( 3959): tags: release-keys
I/flutter ( 3959): supported64BitAbis: [x86_64, arm64-v8a]
I/flutter ( 3959): availableRamSize: 967
I/flutter ( 3959): name: sdk_gphone64_x86_64
I/flutter ( 3959): time: 1753213259000
I/flutter ( 3959): device: emu64xa
I/flutter ( 3959): board: goldfish_x86_64
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;More information can be found on Android via the &lt;a href="https://pub.dev/documentation/device_info_plus/latest/device_info_plus/AndroidBuildVersion-class.html" rel="noopener noreferrer"&gt;&lt;code&gt;AndroidBuildVersion&lt;/code&gt;&lt;/a&gt; object (including the base name, the code name and the release).&lt;/p&gt;

&lt;p&gt;Depending on the platform, a lot of values can be extracted. Here a quick list enumerating few of them (the ones the most interesting to me):&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="https://pub.dev/documentation/device_info_plus/latest/device_info_plus/AndroidDeviceInfo-class.html#instance-properties" rel="noopener noreferrer"&gt;&lt;code&gt;AndroidDeviceInfo&lt;/code&gt;&lt;/a&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://pub.dev/documentation/device_info_plus/latest/device_info_plus/AndroidDeviceInfo/availableRamSize.html" rel="noopener noreferrer"&gt;&lt;code&gt;availableRamSize&lt;/code&gt;&lt;/a&gt; as &lt;code&gt;int&lt;/code&gt;: Current unallocated RAM size of the device in megabytes, extracted from &lt;a href="https://developer.android.com/reference/android/app/ActivityManager.MemoryInfo#availMem" rel="noopener noreferrer"&gt;&lt;code&gt;ActivityManager.MemoryInfo&lt;/code&gt;&lt;/a&gt;;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://pub.dev/documentation/device_info_plus/latest/device_info_plus/AndroidDeviceInfo/board.html" rel="noopener noreferrer"&gt;&lt;code&gt;board&lt;/code&gt;&lt;/a&gt; as &lt;code&gt;String&lt;/code&gt;: The name of the underlying board, like "goldfish", extracted from &lt;a href="https://developer.android.com/reference/android/os/Build#BOARD" rel="noopener noreferrer"&gt;&lt;code&gt;Build.BOARD&lt;/code&gt;&lt;/a&gt;;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://pub.dev/documentation/device_info_plus/latest/device_info_plus/AndroidDeviceInfo/brand.html" rel="noopener noreferrer"&gt;&lt;code&gt;brand&lt;/code&gt;&lt;/a&gt; as &lt;code&gt;String&lt;/code&gt;: The consumer-visible brand with which the product/hardware will be associated, if any, extracted from &lt;a href="https://developer.android.com/reference/android/os/Build#BRAND" rel="noopener noreferrer"&gt;&lt;code&gt;Build.BRAND&lt;/code&gt;&lt;/a&gt;;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://pub.dev/documentation/device_info_plus/latest/device_info_plus/AndroidDeviceInfo/device.html" rel="noopener noreferrer"&gt;&lt;code&gt;device&lt;/code&gt;&lt;/a&gt; as &lt;code&gt;String&lt;/code&gt;: The name of the industrial design, extracted from &lt;a href="https://developer.android.com/reference/android/os/Build#DEVICE" rel="noopener noreferrer"&gt;&lt;code&gt;Build.DEVICE&lt;/code&gt;&lt;/a&gt;;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://pub.dev/documentation/device_info_plus/latest/device_info_plus/AndroidDeviceInfo/fingerprint.html" rel="noopener noreferrer"&gt;&lt;code&gt;fingerprint&lt;/code&gt;&lt;/a&gt; as &lt;code&gt;String&lt;/code&gt;: A string that uniquely identifies this build (Do not attempt to parse this value.), extracted from &lt;a href="https://developer.android.com/reference/android/os/Build#FINGERPRINT" rel="noopener noreferrer"&gt;&lt;code&gt;Build.FINGERPRINT&lt;/code&gt;&lt;/a&gt;;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://pub.dev/documentation/device_info_plus/latest/device_info_plus/AndroidDeviceInfo/hardware.html" rel="noopener noreferrer"&gt;&lt;code&gt;hardware&lt;/code&gt;&lt;/a&gt; as &lt;code&gt;String&lt;/code&gt;: The name of the hardware (from the kernel command line or /proc), extracted from &lt;a href="https://developer.android.com/reference/android/os/Build#HARDWARE" rel="noopener noreferrer"&gt;&lt;code&gt;Build.HARDWARE&lt;/code&gt;&lt;/a&gt;;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://pub.dev/documentation/device_info_plus/latest/device_info_plus/AndroidDeviceInfo/manufacturer.html" rel="noopener noreferrer"&gt;&lt;code&gt;manufacturer&lt;/code&gt;&lt;/a&gt; as &lt;code&gt;String&lt;/code&gt;: The manufacturer of the product/hardware, extracted from &lt;a href="https://developer.android.com/reference/android/os/Build#MANUFACTURER" rel="noopener noreferrer"&gt;&lt;code&gt;Build.MANUFACTURER&lt;/code&gt;&lt;/a&gt;;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://pub.dev/documentation/device_info_plus/latest/device_info_plus/AndroidDeviceInfo/version.html" rel="noopener noreferrer"&gt;&lt;code&gt;version&lt;/code&gt;&lt;/a&gt; as &lt;a href="https://pub.dev/documentation/device_info_plus/latest/device_info_plus/AndroidBuildVersion-class.html" rel="noopener noreferrer"&gt;&lt;code&gt;AndroidBuildVersion&lt;/code&gt;&lt;/a&gt;: Android operating system version values derived from &lt;code&gt;android.os.Build.VERSION&lt;/code&gt;;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="https://pub.dev/documentation/device_info_plus/latest/device_info_plus/IosDeviceInfo-class.html" rel="noopener noreferrer"&gt;&lt;code&gt;IosDeviceInfo&lt;/code&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://pub.dev/documentation/device_info_plus/latest/device_info_plus/IosDeviceInfo/identifierForVendor.html" rel="noopener noreferrer"&gt;&lt;code&gt;identifierForVendor&lt;/code&gt;&lt;/a&gt;: Unique UUID value identifying the current device;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://pub.dev/documentation/device_info_plus/latest/device_info_plus/IosDeviceInfo/modelName.html" rel="noopener noreferrer"&gt;&lt;code&gt;modelName&lt;/code&gt;&lt;/a&gt;: Commercial or user-known model name Examples: iPhone 16 Pro, iPad Pro 11-Inch 3;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://pub.dev/documentation/device_info_plus/latest/device_info_plus/IosDeviceInfo/utsname.html" rel="noopener noreferrer"&gt;&lt;code&gt;utsname&lt;/code&gt;&lt;/a&gt;: Operating system information derived from sys/utsname.h;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="https://pub.dev/documentation/device_info_plus/latest/device_info_plus/LinuxDeviceInfo-class.html" rel="noopener noreferrer"&gt;&lt;code&gt;LinuxDeviceInfo&lt;/code&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://pub.dev/documentation/device_info_plus/latest/device_info_plus/LinuxDeviceInfo/id.html" rel="noopener noreferrer"&gt;&lt;code&gt;id&lt;/code&gt;&lt;/a&gt;: A lower-case string identifying the operating system, excluding any version information and suitable for processing by scripts or usage in generated filenames;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://pub.dev/documentation/device_info_plus/latest/device_info_plus/LinuxDeviceInfo/machineId.html" rel="noopener noreferrer"&gt;&lt;code&gt;machineId&lt;/code&gt;&lt;/a&gt;: A unique machine ID of the local system that is set during installation or boot. The machine ID is hexadecimal, 32-character, lowercase ID;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="https://pub.dev/documentation/device_info_plus/latest/device_info_plus/MacOsDeviceInfo-class.html" rel="noopener noreferrer"&gt;&lt;code&gt;MacOsDeviceInfo&lt;/code&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://pub.dev/documentation/device_info_plus/latest/device_info_plus/MacOsDeviceInfo/systemGUID.html" rel="noopener noreferrer"&gt;&lt;code&gt;systemGUID&lt;/code&gt;&lt;/a&gt;: Device GUID;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="https://pub.dev/documentation/device_info_plus/latest/device_info_plus/WindowsDeviceInfo-class.html" rel="noopener noreferrer"&gt;&lt;code&gt;WindowsDeviceInfo&lt;/code&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://pub.dev/documentation/device_info_plus/latest/device_info_plus/WindowsDeviceInfo/deviceId.html" rel="noopener noreferrer"&gt;&lt;code&gt;deviceId&lt;/code&gt;&lt;/a&gt;: Displayed as "Device ID" in Windows Setting&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The next step will be to generate an unique reproducible identifier from different systems using those information. A list of resources to help thinking about all of that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://developer.android.com/identity/user-data-ids" rel="noopener noreferrer"&gt;Best practices for unique identifiers&lt;/a&gt; from the official Android Developers Website;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://android-developers.googleblog.com/2011/03/identifying-app-installations.html" rel="noopener noreferrer"&gt;Identifying App Installations&lt;/a&gt; from the official Android developers blog;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://github.com/cesarferreira/android-unique-device-id" rel="noopener noreferrer"&gt;&lt;code&gt;android-unique-device-id&lt;/code&gt;&lt;/a&gt; on github;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://stackoverflow.com/questions/4468248/unique-id-of-android-device" rel="noopener noreferrer"&gt;Unique ID of Android device&lt;/a&gt; on StackOverflow;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://gist.github.com/tokoiwesley/27a644312fe657626996f4af0b77a276" rel="noopener noreferrer"&gt;Generate a unique Android Device ID&lt;/a&gt; on gist;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;As usual, happy hacking!&lt;/p&gt;




&lt;p&gt;Cover image by &lt;a href="https://unsplash.com/@elena_ramseier?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" rel="noopener noreferrer"&gt;Elena Ramseier&lt;/a&gt; on &lt;a href="https://unsplash.com/photos/a-large-group-of-green-chairs-1xk8hMP-WHo?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" rel="noopener noreferrer"&gt;Unsplash&lt;/a&gt;&lt;/p&gt;

</description>
      <category>android</category>
      <category>flutter</category>
      <category>mobile</category>
      <category>data</category>
    </item>
    <item>
      <title>WeeklyReview#202641</title>
      <dc:creator>Mathieu Kerjouan</dc:creator>
      <pubDate>Mon, 12 Oct 2026 10:00:00 +0000</pubDate>
      <link>https://dev.to/niamtokik/weeklyreview202641-4beo</link>
      <guid>https://dev.to/niamtokik/weeklyreview202641-4beo</guid>
      <description>&lt;p&gt;This week was quite busy in my code. Redarging my main application/product, I started to implement the database schema with &lt;a href="https://pub.dev/packages/sqflite" rel="noopener noreferrer"&gt;&lt;code&gt;sqflite&lt;/code&gt;&lt;/a&gt; in &lt;code&gt;flutter&lt;/code&gt;. I did also a lot of tests regarding the flexibility of &lt;a href="https://pub.dev/packages/sqflite" rel="noopener noreferrer"&gt;&lt;code&gt;sqflite&lt;/code&gt;&lt;/a&gt;, and its potential limits in my use case. To be honest, I don't really like how this library is working but it should do the jobs for now. I also played with the &lt;a href="https://pub.dev/packages/flutter_quill" rel="noopener noreferrer"&gt;&lt;code&gt;flutter_quill&lt;/code&gt;&lt;/a&gt; text editor library (and also &lt;a href="https://pub.dev/packages/fleather" rel="noopener noreferrer"&gt;&lt;code&gt;fleather&lt;/code&gt;&lt;/a&gt;). Not so complex to use, can produce something pretty cool quick. Finally, the &lt;a href="https://github.com/RandalSchwartz/BlocSignal" rel="noopener noreferrer"&gt;BlocSignal&lt;/a&gt; pattern used in Flutter seems really attractive, lot of examples are available on their repository and it can be a good alternative of my approach (doing everything from scratch to learn).&lt;/p&gt;




&lt;p&gt;It was not expected, but it looks like my motivation was focused to do C code for &lt;a href="https://github.com/niamtokik/mac_randomizer" rel="noopener noreferrer"&gt;&lt;code&gt;mac_randomizer&lt;/code&gt;&lt;/a&gt;. This is definitively a pet project, but C is still one of my favorite language, even if it can be challenging to do some things (e.g. concurrency), it's still great to do kinda low-level code. The source code tree is now clean, the Makefile is minimalist but should work on any system using GNU Makefile. Most of the functions are now sorted by categories in their own source file. The last action was to start working on a minimalist implementation of a Mealy machine, a specific kind of finite state machine, to parse mac addresses, instead of using an external regexp library. Actually, the implementation is a bit hard, not because of the complexity, but because of the interface and the abstraction. My idea is to have something like that:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="c1"&gt;// first tokenize the mac address to validate the&lt;/span&gt;
&lt;span class="c1"&gt;// characters used. Luckily, a mac address only has&lt;/span&gt;
&lt;span class="c1"&gt;// 23 allowed characters: [a-fA-F0-9\-\.\:]&lt;/span&gt;
&lt;span class="c1"&gt;//&lt;/span&gt;
&lt;span class="c1"&gt;// char *string is the raw strings containing the&lt;/span&gt;
&lt;span class="c1"&gt;// mac address.&lt;/span&gt;
&lt;span class="c1"&gt;//&lt;/span&gt;
&lt;span class="c1"&gt;// size_t length is the max size of the string, the&lt;/span&gt;
&lt;span class="c1"&gt;// tokenizer must stop when reading a NUL char or when&lt;/span&gt;
&lt;span class="c1"&gt;// it reaches the length limit&lt;/span&gt;
&lt;span class="c1"&gt;//&lt;/span&gt;
&lt;span class="c1"&gt;// the struct token *tokens is an array of token, where&lt;/span&gt;
&lt;span class="c1"&gt;// each token contains the raw valid character, the &lt;/span&gt;
&lt;span class="c1"&gt;// position of the character and the kind of token (e.g.&lt;/span&gt;
&lt;span class="c1"&gt;// digit, separator).&lt;/span&gt;
&lt;span class="c1"&gt;//&lt;/span&gt;
&lt;span class="c1"&gt;// the tokens should probably be defined inside another&lt;/span&gt;
&lt;span class="c1"&gt;// structure embedded the length of the array. This value&lt;/span&gt;
&lt;span class="c1"&gt;// should be incremented every time a valid character is&lt;/span&gt;
&lt;span class="c1"&gt;// found.&lt;/span&gt;
&lt;span class="kt"&gt;int&lt;/span&gt;
&lt;span class="nf"&gt;tokenizer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;size_t&lt;/span&gt; &lt;span class="n"&gt;length&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;token&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;tokens&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;fsm_start&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;length&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tokens&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// secondly, the parser will get the tokens and will convert&lt;/span&gt;
&lt;span class="c1"&gt;// them into an internal binary representation of the mac&lt;/span&gt;
&lt;span class="c1"&gt;// address (e.g. uint8_t mac_address[6]).&lt;/span&gt;
&lt;span class="c1"&gt;//&lt;/span&gt;
&lt;span class="c1"&gt;// The arguments of this function are similar to the previous&lt;/span&gt;
&lt;span class="c1"&gt;// one. The final result is then stored in the mac_address&lt;/span&gt;
&lt;span class="c1"&gt;// variable.&lt;/span&gt;
&lt;span class="kt"&gt;int&lt;/span&gt;
&lt;span class="nf"&gt;parser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;token&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;tokens&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;size_t&lt;/span&gt; &lt;span class="n"&gt;length&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;uint8_t&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;mac_address&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;fsm_start&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tokens&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;length&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;mac_address&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// the question know is how to design correctly the fsm_start()&lt;/span&gt;
&lt;span class="c1"&gt;// function. It should have the possibility to deal with different&lt;/span&gt;
&lt;span class="c1"&gt;// kind of input, not only char, but also C data-structure. It&lt;/span&gt;
&lt;span class="c1"&gt;// should also be able to deal with different kind of output. Based&lt;/span&gt;
&lt;span class="c1"&gt;// on these requirements, the definition of the function should look&lt;/span&gt;
&lt;span class="c1"&gt;// like the snippet below.&lt;/span&gt;
&lt;span class="c1"&gt;//&lt;/span&gt;
&lt;span class="c1"&gt;// The input argument can be a problem here, at least for the&lt;/span&gt;
&lt;span class="c1"&gt;// mac address parsing feature. Indeed, a string representing a&lt;/span&gt;
&lt;span class="c1"&gt;// mac address only has a few format, with specific length:&lt;/span&gt;
&lt;span class="c1"&gt;//&lt;/span&gt;
&lt;span class="c1"&gt;//   EUI48-IEEE: xx-xx-xx-xx-xx-xx (max length 17)&lt;/span&gt;
&lt;span class="c1"&gt;//   EUI48-IETF: xx:xx:xx:xx:xx:xx (max length 17)&lt;/span&gt;
&lt;span class="c1"&gt;//   EUI48-CISCO: xxxx.xxxx.xxxx (max length 16)&lt;/span&gt;
&lt;span class="c1"&gt;//   EUI64-IEEE: xx-xx-xx-xx-xx-xx-xx-xx (max length 23)&lt;/span&gt;
&lt;span class="c1"&gt;//   EUI64-IETF: xx:xx:xx:xx:xx:xx:xx:xx (max length 23)&lt;/span&gt;
&lt;span class="c1"&gt;//&lt;/span&gt;
&lt;span class="c1"&gt;// the input string should then have a maximal value of 23&lt;/span&gt;
&lt;span class="c1"&gt;// (+1 with NUL), and a minimal value of 17(+1 with NUL). The&lt;/span&gt;
&lt;span class="c1"&gt;// output can also be limited to sizeof(uint8_t)*6=48bits or&lt;/span&gt;
&lt;span class="c1"&gt;// sizeof(uint8_t)*8=64bits. Using the 64bits version is perhaps&lt;/span&gt;
&lt;span class="c1"&gt;// the best choice because an EUI48 can be converted to an EUI64&lt;/span&gt;
&lt;span class="c1"&gt;// and vice versa. Note: I don't even think it's possible to&lt;/span&gt;
&lt;span class="c1"&gt;// compress this value, it will probably add more complexity&lt;/span&gt;
&lt;span class="c1"&gt;// for no real benefits on the long run.&lt;/span&gt;
&lt;span class="kt"&gt;int&lt;/span&gt;
&lt;span class="nf"&gt;fsm_start&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;input&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="kt"&gt;size_t&lt;/span&gt; &lt;span class="n"&gt;input_length&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;output&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;init&lt;/span&gt;
&lt;span class="p"&gt;){&lt;/span&gt;
  &lt;span class="c1"&gt;// do something here.&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// the states must also be defined somewhere. states can&lt;/span&gt;
&lt;span class="c1"&gt;// be created dynamically by instantiating different kind&lt;/span&gt;
&lt;span class="c1"&gt;// of object and pushing them together, or creating them&lt;/span&gt;
&lt;span class="c1"&gt;// "statically" in their own data-structure with their&lt;/span&gt;
&lt;span class="c1"&gt;// own callback functions. One of the idea is to create&lt;/span&gt;
&lt;span class="c1"&gt;// something like the code below.&lt;/span&gt;
&lt;span class="c1"&gt;//&lt;/span&gt;
&lt;span class="c1"&gt;// The handler_enter callback is called only when a transition&lt;/span&gt;
&lt;span class="c1"&gt;// occurs between states.&lt;/span&gt;
&lt;span class="c1"&gt;//&lt;/span&gt;
&lt;span class="c1"&gt;// The handler_input callback is executed when an input&lt;/span&gt;
&lt;span class="c1"&gt;// is received.&lt;/span&gt;
&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;handler_enter&lt;/span&gt;&lt;span class="p"&gt;)(&lt;/span&gt;&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;handler_input&lt;/span&gt;&lt;span class="p"&gt;)(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;input&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;output&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you can see, it's a good mental exercise to find the right way to implement something like that in C. In fact, a mealy (or moore) FSM are being use with Regexp but also with other complex protocols like TCP. Reimplementing something like that to parse well specified data like a mac address is probably the best choice, and, if correctly done, it could also be used to encode as well.&lt;/p&gt;

&lt;p&gt;Anyway, here some implementations from github:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://github.com/ajrisi/fsm" rel="noopener noreferrer"&gt;&lt;strong&gt;ajrisi/fsm&lt;/strong&gt;&lt;/a&gt;;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/cferwin/microFSM" rel="noopener noreferrer"&gt;&lt;strong&gt;cferwin/microFSM&lt;/strong&gt;&lt;/a&gt;;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/At-EC/At-FSM" rel="noopener noreferrer"&gt;&lt;strong&gt;At-EC/At-FSM&lt;/strong&gt;&lt;/a&gt;;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/TheHumbleTransistor/HTHSM" rel="noopener noreferrer"&gt;&lt;strong&gt;TheHumbleTransistor/HTHSM&lt;/strong&gt;&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;More implementation examples can be also found in userland from OpenBSD, FreeBSD and NetBSD projects. Many of those tools can have an implementation of a finite state machine.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;OpenBSD:

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://github.com/openbsd/src/blob/master/usr.bin/patch/ed.c" rel="noopener noreferrer"&gt;&lt;code&gt;usr.bin/patch/ed.c&lt;/code&gt;&lt;/a&gt;: it contains a small finite state machine implementation used to parse commands&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/openbsd/src/blob/master/games/bs/bs.c" rel="noopener noreferrer"&gt;&lt;code&gt;games/bs/bs.c&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/openbsd/src/blob/master/usr.sbin/npppd/npppd/fsm.c" rel="noopener noreferrer"&gt;&lt;code&gt;usr.sbin/npppd/npppd/fsm.c&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/openbsd/src/blob/master/usr.sbin/pppd/fsm.c" rel="noopener noreferrer"&gt;&lt;code&gt;usr.sbin/pppd/fsm.c&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/openbsd/src/blob/master/lib/libc/gen/unvis.c" rel="noopener noreferrer"&gt;&lt;code&gt;lib/libc/gen/unvis.c&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;FreeBSD:

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/freebsd/freebsd-src/blob/main/crypto/openssl/ssl/statem/statem.c" rel="noopener noreferrer"&gt;&lt;code&gt;crypto/openssl/ssl/statem/statem.c&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;NetBSD:

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/NetBSD/src/blob/trunk/libexec/telnetd/state.c" rel="noopener noreferrer"&gt;&lt;code&gt;libexec/telnetd/state.c&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/NetBSD/src/blob/trunk/sbin/init/init.c" rel="noopener noreferrer"&gt;&lt;code&gt;sbin/init/init.c&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;Most of my posts are currently stuck in draft mode due to that, but I like the weekly review format. It is a good summary containing a lot of information in one place. Then, I think most of the coming publications will use this format.&lt;/p&gt;

&lt;h1&gt;
  
  
  Coding
&lt;/h1&gt;

&lt;p&gt;📝 &lt;a href="http://www.phoenixframework.org/blog/heex-compilation-deep-dive-liveview-1-2" rel="noopener noreferrer"&gt;&lt;strong&gt;A deep dive into HEEx compilation from LiveView 1.2&lt;/strong&gt;&lt;/a&gt;: A post explaining the foundation of the HEEx template systems present in Phoenix LiveView. I did not know it was tokenized. In fact, this is a very good news... It is becoming closer to the way clojure is dealing with HTML.&lt;/p&gt;

&lt;p&gt;📝 &lt;a href="https://ghuntley.com/lisp/" rel="noopener noreferrer"&gt;&lt;strong&gt;an application in lisp you grow by talking to it&lt;/strong&gt;&lt;/a&gt;: LISP is probably one of the greatest language of all time, in this article, the program is created by talking to an LLM during a coding session.&lt;/p&gt;

&lt;p&gt;🏗️ &lt;a href="https://github.com/weavefoundry/weavec" rel="noopener noreferrer"&gt;&lt;strong&gt;WeaveC&lt;/strong&gt;&lt;/a&gt;: A C compiler with inferred ownership and borrow checking for Rust-style memory safety.&lt;/p&gt;

&lt;p&gt;🌐 &lt;a href="https://elixir.menu/" rel="noopener noreferrer"&gt;&lt;strong&gt;Tools for your Elixir app&lt;/strong&gt;&lt;/a&gt;: A starting point for each kind of application. Recommended tools, why we use them, and when to choose something else.&lt;/p&gt;

&lt;p&gt;🏗️ &lt;a href="https://github.com/moznion/cccc" rel="noopener noreferrer"&gt;&lt;strong&gt;cccc&lt;/strong&gt;&lt;/a&gt;: measures Cognitive Complexity (SonarSource / G. Ann Campbell) and Cyclomatic Complexity (McCabe). I used similar tools in the past, like &lt;code&gt;ccc&lt;/code&gt; and &lt;code&gt;scc&lt;/code&gt; or &lt;code&gt;sccc&lt;/code&gt;. Nice to have, even before if you add it in your CI/CD to evaluate the complexity of a commit.&lt;/p&gt;

&lt;p&gt;📑 &lt;a href="https://lwn.net/Articles/1095811/" rel="noopener noreferrer"&gt;&lt;strong&gt;Reducing undefined behavior in the C language&lt;/strong&gt;&lt;/a&gt;: undefined behavior in C is a nightmare. Probably one of the most complex part of the language, and it can lead to total disaster. This post is presenting the solution to avoid common mistakes and find a way to create safer C code. Actually, this is from a &lt;a href="https://www.youtube.com/watch?v=dhlYcmX_oBQ&amp;amp;list=PLEVVgAZOU9P8&amp;amp;index=14" rel="noopener noreferrer"&gt;talk&lt;/a&gt;, and the slides are &lt;a href="https://uecker.codeberg.page/kernel-recipes.pdf" rel="noopener noreferrer"&gt;available online&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;📝 &lt;a href="https://blog.llvm.org/2011/05/what-every-c-programmer-should-know.html" rel="noopener noreferrer"&gt;&lt;strong&gt;What Every C Programmer Should Know About Undefined Behavior #1/3&lt;/strong&gt;&lt;/a&gt;: the first article of a series about undefined behavior in C.&lt;/p&gt;

&lt;p&gt;📝 &lt;a href="https://keleshev.com/abstract-syntax-tree-an-example-in-c/" rel="noopener noreferrer"&gt;&lt;strong&gt;Abstract Syntax Tree, An Example in C&lt;/strong&gt;&lt;/a&gt;: a short publication with nice example to explain how to implement and use an AST.&lt;/p&gt;

&lt;p&gt;📝 &lt;a href="https://keleshev.com/one-pass-compiler-primer" rel="noopener noreferrer"&gt;&lt;strong&gt;One-pass Compiler&lt;/strong&gt;&lt;/a&gt;: a nice trick to compile code directly without passed inside different layer.&lt;/p&gt;

&lt;p&gt;📖 &lt;a href="https://keleshev.com/compiling-to-assembly-from-scratch/#table-of-contents" rel="noopener noreferrer"&gt;&lt;strong&gt;Compiling to Assembly from Scratch&lt;/strong&gt;&lt;/a&gt;: a book by the author of the two previous posts. neat.&lt;/p&gt;

&lt;p&gt;📑 &lt;a href="https://dl.gi.de/server/api/core/bitstreams/95165c87-561d-4b35-bed9-6175e1948a5a/content" rel="noopener noreferrer"&gt;&lt;strong&gt;CASM: Implementing an Abstract State Machine based Programming Language&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  System
&lt;/h1&gt;

&lt;p&gt;📝 &lt;a href="https://rsadowski.de/posts/2026/update-relayd-and-httpd/" rel="noopener noreferrer"&gt;&lt;strong&gt;Headers Up! What's New in httpd and relayd&lt;/strong&gt;&lt;/a&gt;: HTTP header manipulation support and request filtering. I'm still using nginx, but &lt;code&gt;httpd&lt;/code&gt; is becoming really better every new release.&lt;/p&gt;

&lt;p&gt;📝 &lt;a href="https://marc.info/?l=openbsd-tech&amp;amp;m=179114222343483&amp;amp;w=2" rel="noopener noreferrer"&gt;&lt;strong&gt;Locking down openat(2) and friends with O_BELOW and F_BELOW&lt;/strong&gt;&lt;/a&gt;: a mail-exchange describing the (future?) &lt;code&gt;openat&lt;/code&gt; function to open file with relative path (and more safety).&lt;/p&gt;

&lt;p&gt;🏗️ &lt;a href="https://github.com/Genymobile/scrcpy" rel="noopener noreferrer"&gt;&lt;strong&gt;scrcpy&lt;/strong&gt;&lt;/a&gt;: Display and control your Android device.&lt;/p&gt;

&lt;p&gt;🏗️ &lt;a href="https://github.com/floci-io/floci" rel="noopener noreferrer"&gt;&lt;strong&gt;floci&lt;/strong&gt;&lt;/a&gt;: gives you AWS-shaped services on your machine without requiring a cloud account, an auth token, or paid feature gates. &lt;/p&gt;

&lt;p&gt;🏗️ &lt;a href="https://github.com/riscv/learn" rel="noopener noreferrer"&gt;&lt;strong&gt;riscv/learn&lt;/strong&gt;&lt;/a&gt;: A community-driven, continuously updated compilation of RISC-V learning resources. Content is organized by topic and experience level to help you discover courses, software, documentation, and articles efficiently.&lt;/p&gt;

&lt;p&gt;📖 &lt;a href="https://simonjohnthompson.github.io/haskellcraft/" rel="noopener noreferrer"&gt;&lt;strong&gt;Haskell: The Craft of Functional Programming&lt;/strong&gt;&lt;/a&gt;: revised version.&lt;/p&gt;

&lt;p&gt;🏗️ &lt;a href="https://www.dpdk.org/" rel="noopener noreferrer"&gt;&lt;strong&gt;DPDK (Data Plane Development Kit)&lt;/strong&gt;&lt;/a&gt;: an open source framework for fast packet processing on standard hardware. It runs in cloud infrastructure, telecom networks, financial exchanges, particle accelerators, and radio telescopes. Most of your traffic already runs through it. Start by reviewing a patch, no account or setup required. I discovered it was also running not only on Linux... I need to try that.&lt;/p&gt;

&lt;p&gt;📝 &lt;a href="https://ghuntley.com/unikernels/" rel="noopener noreferrer"&gt;&lt;strong&gt;unikernels were hard. key word: were&lt;/strong&gt;&lt;/a&gt;: unikernel IS THE WAY TO GO, but I still this a complex technology mixing a lot of features from many different part of any systems. In fact, this is really close to microkernel, and both are, to me, two things that should be merged together.&lt;/p&gt;

&lt;h1&gt;
  
  
  Network
&lt;/h1&gt;

&lt;p&gt;🏗️ &lt;a href="https://www.openvswitch.org/" rel="noopener noreferrer"&gt;&lt;strong&gt;Open vSwitch (OVS)&lt;/strong&gt;&lt;/a&gt;: a production quality, multilayer virtual switch, designed to enable massive network automation through programmatic extension, while still supporting standard management interfaces and protocols.&lt;/p&gt;

&lt;p&gt;🏗️ &lt;a href="https://www.ovn.org/en/" rel="noopener noreferrer"&gt;&lt;strong&gt;Open Virtual Network&lt;/strong&gt;&lt;/a&gt;: a series of daemons for the Open vSwitch that translate virtual network configurations into OpenFlow.&lt;/p&gt;

&lt;h1&gt;
  
  
  Database
&lt;/h1&gt;

&lt;p&gt;🏗️ &lt;a href="https://github.com/pingcap/awesome-database-learning" rel="noopener noreferrer"&gt;&lt;strong&gt;Awesome Database Learning&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;🏗️ &lt;a href="https://github.com/pgvector/pgvector" rel="noopener noreferrer"&gt;&lt;strong&gt;pgvector&lt;/strong&gt;&lt;/a&gt;: Open-source vector similarity search for Postgres&lt;/p&gt;

&lt;h1&gt;
  
  
  Security
&lt;/h1&gt;

&lt;p&gt;📝 &lt;a href="https://forum.itsallwidgets.com/t/malicious-flutter-package-while-it-have-a-clean-code/4960" rel="noopener noreferrer"&gt;&lt;strong&gt;Malicious Flutter Package while it have a Clean Code?&lt;/strong&gt;&lt;/a&gt;: malware present in &lt;code&gt;example&lt;/code&gt; directory inside a flutter project. Don't trust blindly all projects.&lt;/p&gt;

&lt;p&gt;📝 &lt;a href="https://projectzero.google/2026/10/emergency-patching.html" rel="noopener noreferrer"&gt;&lt;strong&gt;How to fix a bug in a fix&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;📝 &lt;a href="https://blog.google/security/chromes-response-to-recent-cctld-registry-hijacks/" rel="noopener noreferrer"&gt;&lt;strong&gt;Chrome's Response to Recent ccTLD Registry Hijacks&lt;/strong&gt;&lt;/a&gt;: Following recent .gh, .sl, and .as ccTLD domain hijacks, Chrome immediately blocked unauthorized HTTPS certificates via CRLSets to protect users automatically. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://beaksec.github.io/posts/telegram-desktop-one-click-account-takeover/" rel="noopener noreferrer"&gt;&lt;strong&gt;Telegram Desktop: one-click account takeover via IPC injection&lt;/strong&gt;&lt;/a&gt;: a post describing the CVE-2026-107181, where one malicious actor can take control of a group by sharing a telegram link and opening it on the telegram desktop application. The problem is from the URI parser, when dealing with semicolons. That's an interesting attack, because many application can be ported on different systems, like Signal or SimpleXChat, and depending of the languages/tools used, some part of the can use different routines.&lt;/p&gt;

&lt;h1&gt;
  
  
  Security/Cryptography
&lt;/h1&gt;

&lt;p&gt;📝 &lt;a href="https://blog.trailofbits.com/2026/10/02/sequencehash-multihashing-for-the-rest-of-us/" rel="noopener noreferrer"&gt;&lt;strong&gt;SequenceHash: multihashing for the rest of us&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;🌐 &lt;a href="https://www.yukon.org/hashsmash" rel="noopener noreferrer"&gt;&lt;strong&gt;Hash Smash&lt;/strong&gt;&lt;/a&gt;: Find ordinary collision attacks that reach more rounds with less total computation. Select a hash function’s chart, then one of its two round counts.&lt;/p&gt;

&lt;p&gt;📑 &lt;a href="https://eprint.iacr.org/2026/2363.pdf" rel="noopener noreferrer"&gt;&lt;strong&gt;MiniSHAKE&lt;/strong&gt;&lt;/a&gt;: an extendable output function based on Keccak, with unlimited size output.&lt;/p&gt;

&lt;p&gt;📑 &lt;a href="https://keccak.team/files/TurboSHAKE.pdf" rel="noopener noreferrer"&gt;&lt;strong&gt;TurboSHAKE&lt;/strong&gt;&lt;/a&gt;: an extendable output function based on Keccak, with less rounds to improve performance.&lt;/p&gt;

&lt;p&gt;🌐 &lt;a href="https://keylength.goodkey.co/" rel="noopener noreferrer"&gt;&lt;strong&gt;Key Length&lt;/strong&gt;&lt;/a&gt;: The minimum key sizes each source publishes for protecting data until a given year. &lt;/p&gt;

&lt;h1&gt;
  
  
  Embedded
&lt;/h1&gt;

&lt;p&gt;🏗️ &lt;a href="https://github.com/usamahz/cpu-performance-engineering" rel="noopener noreferrer"&gt;&lt;strong&gt;CPU Performance Engineering&lt;/strong&gt;&lt;/a&gt;: A reading path for CPU performance engineering, from one instruction to production inference. Primary sources only, with a runnable benchmark for every section.&lt;/p&gt;

&lt;p&gt;📝 &lt;a href="https://hackaday.com/2026/10/05/the-fpga-chronicles-open-source-it/" rel="noopener noreferrer"&gt;&lt;strong&gt;The FPGA Chronicles: Open Source It&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;🏗️ &lt;a href="https://github.com/BeRo1985/pasriscv" rel="noopener noreferrer"&gt;&lt;strong&gt;PasRISCV&lt;/strong&gt;&lt;/a&gt;:A RISC-V RV64GCV/RVA23 emulator written in Object Pascal. It simulates processor cores, memory, I/O, and much more.&lt;/p&gt;

&lt;h1&gt;
  
  
  Update/Upgrade
&lt;/h1&gt;

&lt;p&gt;🔄 &lt;a href="https://github.com/benoitc/hackney/releases/tag/4.8.5" rel="noopener noreferrer"&gt;&lt;strong&gt;hackney 4.8.5&lt;/strong&gt;&lt;/a&gt;: bug fixes.&lt;/p&gt;

&lt;p&gt;🔄 &lt;a href="https://ninenines.eu/articles/cowboy-2.20.0/" rel="noopener noreferrer"&gt;&lt;strong&gt;Cowboy 2.20&lt;/strong&gt;&lt;/a&gt;: security and bug fixes.&lt;/p&gt;

&lt;p&gt;🔄 &lt;a href="https://undeadly.org/cgi?action=article;sid=20261007052424" rel="noopener noreferrer"&gt;&lt;strong&gt;LibreSSL 4.2.2 and 4.3.3&lt;/strong&gt;&lt;/a&gt;: security and bug fixes.&lt;/p&gt;

&lt;h1&gt;
  
  
  Computer Science
&lt;/h1&gt;

&lt;p&gt;📑 &lt;a href="https://web.iitd.ac.in/~debanjan/ELL318_Lecture7_MealyandMooreMachines_DBRevised.pdf" rel="noopener noreferrer"&gt;&lt;strong&gt;Digital Hardware Design DFA, Mealy and Moore Machines&lt;/strong&gt;&lt;/a&gt;: a lecture on Mealy/Moore machines&lt;/p&gt;

&lt;p&gt;📑 &lt;a href="https://arxiv.org/pdf/2206.04944" rel="noopener noreferrer"&gt;&lt;strong&gt;A Report on Achieving Complete Regular-Expression Matching using Mealy Machines&lt;/strong&gt;&lt;/a&gt;: an interesting (but complex) publication about regexp and finite state machine to match exact pattern.&lt;/p&gt;

&lt;p&gt;📑 &lt;a href="https://link.springer.com/content/pdf/10.1007/978-3-031-08679-3_8.pdf" rel="noopener noreferrer"&gt;&lt;strong&gt;Effective Reductions of Mealy Machines&lt;/strong&gt;&lt;/a&gt;: reducing mealy machines states and transitions.&lt;/p&gt;

&lt;h1&gt;
  
  
  Misc
&lt;/h1&gt;

&lt;p&gt;📝 &lt;a href="https://aeon.co/essays/your-brain-does-not-process-information-and-it-is-not-a-computer" rel="noopener noreferrer"&gt;&lt;strong&gt;The empty brain&lt;/strong&gt;&lt;/a&gt;: an amazing post about brain information processing. The brain is not storing information like a computer (a stream of bits), and in fact, it is not the only organ to "store it". It stores experiences, and experiences are different between every people alive, then, it will be impossible to "copy" experiences between humans. In fact, like the author is explaining in his publication, even if all neurons' states were extracted, copied and connected together, it will have no meaning because it would be outside of the body where the experiences have been learned.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Because the Information Processing metaphor is not even slightly valid, we will never have to worry about a human mind going amok in cyberspace; alas, we will also never achieve immortality through downloading. [...] &lt;strong&gt;We are organisms, not computers&lt;/strong&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;📝 &lt;a href="https://frenchbreaches.com/blog/victime-dune-fuite-de-donnees-voici-dans-quels-cas-vous-pouvez-reclamer-une-indemnisation" rel="noopener noreferrer"&gt;&lt;strong&gt;Victime d’une fuite de données ? Voici dans quels cas vous pouvez réclamer une indemnisation&lt;/strong&gt;&lt;/a&gt;: see also that on the &lt;a href="https://www.cnil.fr/fr/violations-de-donnees-personnelles-cas-indemnite" rel="noopener noreferrer"&gt;CNIL website&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;📝 &lt;a href="https://www.morningstar.com/news/marketwatch/20261008113/a-strategist-who-called-the-asian-financial-crisis-sees-parallels-with-the-ai-boom" rel="noopener noreferrer"&gt;&lt;strong&gt;A strategist who called the Asian financial crisis sees parallels with the AI boom&lt;/strong&gt;&lt;/a&gt;: another indicator the "AI" boom is not really doing what every one expect. I wanted to read &lt;a href="https://www.zerohedge.com/markets/myth-ais-miracle-albert-edwards-spots-same-fatal-flaw-sank-asia-1997" rel="noopener noreferrer"&gt;The Myth Of AI's Miracle: Albert Edwards Spots The Same Fatal Flaw That Sank Asia In 1997&lt;/a&gt;, but, well, it is a premium article.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;the productivity payoff from AI remains a forecast, rather than an observation [...] No AI productivity boost in the data yet [...] too many people believed the beguiling narrative and as a consequence, lent these economies cheap, abundant capital which was misallocated.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;🐦 &lt;a href="https://threadout.app/thread/2108530300494230009-the-signs-that-the-ai-boom-is-built-on-fake-revenue-are-now" rel="noopener noreferrer"&gt;&lt;strong&gt;THE SIGNS THAT THE AI BOOM IS BUILT ON FAKE REVENUE ARE NOW HERE. Here is what is really happening&lt;/strong&gt;&lt;/a&gt;: a thread about what could happen with the AI financial - SCAM - scheme. Anyway, it smells really bad, even worse than the crypto-currency bubble.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Every time an AI startup raises money at a higher valuation, the investor raises the value of its stake on its books and counts the increase as income. &lt;strong&gt;No cash comes in. The profit is on paper.&lt;/strong&gt; [...] A large part of the sales and profits these companies report depends on money that investors, including the tech giants themselves, keep putting into OpenAI and Anthropic. If that funding slows, the backlog, the sales and the paper profits all weaken together.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h1&gt;
  
  
  Leaks of the week
&lt;/h1&gt;

&lt;p&gt;🐦 &lt;a href="https://x.com/DarkWebInformer/status/2106514093717008857?s=20" rel="noopener noreferrer"&gt;&lt;strong&gt;Tata Consultancy Services&lt;/strong&gt;&lt;/a&gt;: source code and credentials leaked.&lt;/p&gt;

&lt;p&gt;🐦 &lt;a href="https://x.com/DarkWebInformer/status/2106471572257050887?s=20" rel="noopener noreferrer"&gt;&lt;strong&gt;UAE government&lt;/strong&gt;&lt;/a&gt;: 17 millions entries from UAE government-related software licensing database&lt;/p&gt;

&lt;p&gt;🐦 &lt;a href="https://x.com/DarkWebInformer/status/2106465040115159224?s=20" rel="noopener noreferrer"&gt;&lt;strong&gt;Get covered&lt;/strong&gt;&lt;/a&gt;: more than 1 million customer records including email, phone numbers, physical address and more.&lt;/p&gt;

&lt;p&gt;🐦 &lt;a href="https://x.com/DarkWebInformer/status/2106403088835694632?s=20" rel="noopener noreferrer"&gt;&lt;strong&gt;CAPEB&lt;/strong&gt;&lt;/a&gt;: Around 4 millions records including emails and phone numbers.&lt;/p&gt;

&lt;p&gt;🐦 &lt;a href="https://x.com/CR1337/status/2107039062469353812?s=20" rel="noopener noreferrer"&gt;&lt;strong&gt;Denmark government&lt;/strong&gt;&lt;/a&gt;: 8.8 millions people impacted, Danish citizens and emigrates. The leak include  Social security number, Age, Sex, Family relations, Physical address, Protected addresses and Sex change.&lt;/p&gt;




&lt;p&gt;&lt;iframe class="tweet-embed" id="tweet-2107477791549907153-99" src="https://platform.twitter.com/embed/Tweet.html?id=2107477791549907153"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-2107477791549907153-99');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=2107477791549907153&amp;amp;theme=dark"
  }



&lt;/p&gt;

&lt;p&gt;&lt;a href="https://x.com/Arikalabs/status/2106511599276061021?s=20" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fdenxxeanzt6ajmr7p99t.png" alt=" " width="598" height="138"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://x.com/SmokeAwayyy/status/2106566046350258515?s=20" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fpr7kg56fgpi8qmo9lnxg.png" alt=" " width="598" height="218"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://x.com/AmanVirk1/status/2106610500218061051?s=20" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Flt7wlurausdxrnbp0cky.png" alt=" " width="598" height="198"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://x.com/agounardes/status/2106890198369947659?s=20" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fi0c4nlas90znx8k3cng3.png" alt=" " width="598" height="622"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://x.com/JustDeezGuy/status/2106931338343526541?s=20" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fxl1fj6kq6h5ulrq5wza9.png" alt=" " width="598" height="308"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://x.com/wangzhr4/status/2107059715956224145?s=20" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fob72kp3wotctnzkrqfcf.png" alt=" " width="598" height="384"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://x.com/ortegaalfredo/status/2107218272416587958?s=20" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Feylhovw221rw0mzvfzsp.png" alt=" " width="598" height="280"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fep1kid7iqgy1mo3xrkeg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fep1kid7iqgy1mo3xrkeg.png" alt=" " width="598" height="98"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fnfj43v1633ofmxxbprn5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fnfj43v1633ofmxxbprn5.png" alt=" " width="598" height="134"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://x.com/pmddomingos/status/2107598154799738891?s=20" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F84epcdo057elvdf3zauu.png" alt=" " width="598" height="158"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://x.com/louiseivan/status/2107542657874661780?s=20" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F7htdee7zdxpf6ralc8m9.png" alt=" " width="598" height="120"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://x.com/Ross__Hendricks/status/2108249887435620559?s=20" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fgt4ck2e1hlgut9iv5lvi.png" alt=" " width="598" height="138"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://x.com/IceSolst/status/2108543740411584799?s=20" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fqx24s1rxk9zbb0ox8eb5.png" alt=" " width="598" height="244"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://x.com/veorq/status/2108965379829797059?s=20" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fk870134p86im0ny2ca4c.png" alt=" " width="598" height="98"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F9qep2bbnh7laxp9h8oia.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F9qep2bbnh7laxp9h8oia.png" alt=" " width="680" height="675"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;Cover Image by &lt;a href="https://unsplash.com/@puregeorgia?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" rel="noopener noreferrer"&gt;Alfred Schrock&lt;/a&gt; on &lt;a href="https://unsplash.com/photos/yellow-leaves-on-black-and-yellow-concrete-road-C7E8WTsvkmY?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" rel="noopener noreferrer"&gt;Unsplash&lt;/a&gt;&lt;/p&gt;

</description>
      <category>weekly</category>
      <category>review</category>
    </item>
    <item>
      <title>WeeklyReview#202640</title>
      <dc:creator>Mathieu Kerjouan</dc:creator>
      <pubDate>Mon, 05 Oct 2026 10:00:00 +0000</pubDate>
      <link>https://dev.to/niamtokik/weeklyreview202640-5b8i</link>
      <guid>https://dev.to/niamtokik/weeklyreview202640-5b8i</guid>
      <description>&lt;p&gt;Another week of doing Erlang/Elixir code on &lt;code&gt;expki&lt;/code&gt; project. Again, that's mostly a sandbox to remove my 2 years rust doing only Erlang code and infrastructure stuff. Things are moving though, and I have a way to deal with the &lt;code&gt;public_key&lt;/code&gt; module from Elixir. It's not perfect yet and can be optimized, but it should do the job. I think you will read that in a post very soon.&lt;/p&gt;




&lt;p&gt;My way to extract macros and records from Erlang source code has been moved to its own module called &lt;a href="https://github.com/niamtokik/preprocessing" rel="noopener noreferrer"&gt;&lt;code&gt;preprocessing&lt;/code&gt;&lt;/a&gt;. It is currently being tested, but it should work correctly. Many things remain to be added though, like the support for dynamic macros and perhaps other attributes from Erlang.&lt;/p&gt;




&lt;p&gt;Dev.to is buggy. One big article I started to write few days ago was practically destroyed because of cache issue on the browser. When editing the file from the dashboard, an old version was displayed instead of the latest one. Don't save. Don't publish. Close the window, logout from your dev.to account and reconnect.&lt;/p&gt;




&lt;p&gt;&lt;a href="https://github.com/niamtokik/publish" rel="noopener noreferrer"&gt;&lt;code&gt;publish&lt;/code&gt;&lt;/a&gt; is now able to fetch all the posts from dev.to using the API and curl. I did not have a lot of time working on it this week though. It would be really nice to migrate few  my articles very soon on my own domain.&lt;/p&gt;




&lt;p&gt;&lt;a href="https://github.com/niamtokik/mac_randomizer" rel="noopener noreferrer"&gt;&lt;code&gt;mac_randomizer&lt;/code&gt;&lt;/a&gt; was a pet project I got year ago, simply an idea at first. I wanted to do a bit of C this week and started to play with that. Not a really serious project though.&lt;/p&gt;

&lt;h1&gt;
  
  
  Coding
&lt;/h1&gt;

&lt;p&gt;📖 &lt;a href="https://github.com/cs341-illinois/coursebook" rel="noopener noreferrer"&gt;&lt;strong&gt;Course book&lt;/strong&gt;&lt;/a&gt;: Open Source Introductory Systems Programming Textbook for the University of Illinois&lt;/p&gt;

&lt;p&gt;🌐 &lt;a href="https://zero-js.vercel.app/" rel="noopener noreferrer"&gt;&lt;strong&gt;zero-js&lt;/strong&gt;&lt;/a&gt;: compiling code in HTML/CSS directly, without javascript.&lt;/p&gt;

&lt;p&gt;📝 &lt;a href="https://david.alvarezrosa.com/posts/optimizing-a-lock-free-ring-buffer/" rel="noopener noreferrer"&gt;&lt;strong&gt;Optimizing a Lock-Free Ring Buffer&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;📝 &lt;a href="https://engineering.legendsoflearning.com/posts/generating-functions/" rel="noopener noreferrer"&gt;&lt;strong&gt;Simplify Function Generation in Elixir with Macros&lt;/strong&gt;&lt;/a&gt;: a quick reminder to generate function in Elixir with macros. A good way to do meta-programming.&lt;/p&gt;

&lt;p&gt;📝 &lt;a href="https://elixir.hexdocs.pm/anonymous-functions.html" rel="noopener noreferrer"&gt;&lt;strong&gt;Elixir Anonymous functions&lt;/strong&gt;&lt;/a&gt;: official documentation about anonymous/lambda functions in Elixir.&lt;/p&gt;

&lt;p&gt;📝 &lt;a href="https://elixir.hexdocs.pm/main/quote-and-unquote.html" rel="noopener noreferrer"&gt;&lt;strong&gt;Elixir Quote and unquote&lt;/strong&gt;&lt;/a&gt;: official documentation about metaprogramming elixir with quote and unquote.&lt;/p&gt;

&lt;p&gt;🏗️ &lt;a href="https://github.com/tuist/pulso" rel="noopener noreferrer"&gt;&lt;strong&gt;pulso&lt;/strong&gt;&lt;/a&gt;: A headless, open-source observability backend: unified logs, metrics, and traces access, built-in alerting, and a native Model Context Protocol (MCP) interface, built on Elixir/OTP with a Rust hot path for columnar data.&lt;/p&gt;

&lt;p&gt;🏗️ &lt;a href="https://github.com/imboy-pub/erlang_pay" rel="noopener noreferrer"&gt;&lt;strong&gt;erlang_pay&lt;/strong&gt;&lt;/a&gt;:  A pure-Erlang payment gateway library for Alipay (App pay), WeChat Pay v3 (JSAPI/Native) and Stripe (PaymentIntent).&lt;/p&gt;

&lt;p&gt;📝 &lt;a href="https://blog.codingconfessions.com/p/how-copy-on-write-works-with-memory" rel="noopener noreferrer"&gt;&lt;strong&gt;How Copy-on-Write Works with Memory-Mapped Files&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;📝 &lt;a href="https://kobzol.github.io/rust/rustc/2025/05/20/disable-debuginfo-to-improve-rust-compile-times.html" rel="noopener noreferrer"&gt;&lt;strong&gt;Disable debuginfo to improve Rust compile times&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;📝 &lt;a href="https://pikuma.com/blog/comanche-maps-reverse-engineering" rel="noopener noreferrer"&gt;&lt;strong&gt;Reverse Engineering Novalogic's Comanche Terrain Maps&lt;/strong&gt;&lt;/a&gt;: not an expert in game programming, but reverse engineering is an amazing field. This article explains how to reverse the maps from an old game, it's in C, and it's a great one! I liked this quote:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Programmers in the early 90s didn't reinvent everything. They used the formats and tools the artists already had, like PCX files straight out of a paint program, and saved their cleverness for the parts that really needed it: the renderer.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;📝 &lt;a href="https://buttondown.com/hillelwayne/archive/what-tla-can-and-cant-check/" rel="noopener noreferrer"&gt;&lt;strong&gt;What TLA+ can and can't check&lt;/strong&gt;&lt;/a&gt;: TLA+ fascinated me few years ago, and I started to learn it by myself. Unfortunately, I was not really good with it. Languages formal verifications/specifications can be challenging to learn, even more if you don't have any a real usage for them. It's good to read a post on this language, even more to clarify what TLA+ can do or not.&lt;/p&gt;

&lt;p&gt;📝 &lt;a href="https://best.openssf.org/Compiler-Hardening-Guides/Compiler-Options-Hardening-Guide-for-C-and-C++.html" rel="noopener noreferrer"&gt;&lt;strong&gt;Compiler Options Hardening Guide for C and C++&lt;/strong&gt;&lt;/a&gt;: an extremely useful guide and reference to correctly set C compiler flags for hardened applications.&lt;/p&gt;

&lt;h1&gt;
  
  
  Database
&lt;/h1&gt;

&lt;p&gt;🏗️ &lt;a href="https://github.com/dbulashev/dasha" rel="noopener noreferrer"&gt;&lt;strong&gt;Dasha&lt;/strong&gt;&lt;/a&gt;: PostgreSQL performance dashboard for analyzing database cluster health, identifying problems, and providing optimization recommendations.&lt;/p&gt;

&lt;h1&gt;
  
  
  System
&lt;/h1&gt;

&lt;p&gt;🏗️ &lt;a href="https://minios.dev/" rel="noopener noreferrer"&gt;&lt;strong&gt;MiniOS&lt;/strong&gt;&lt;/a&gt;: A full-featured desktop environment with a wide range of applications. Professional tools for creativity and development.&lt;/p&gt;

&lt;p&gt;🏗️ &lt;a href="https://vinix-os.org/" rel="noopener noreferrer"&gt;&lt;strong&gt;Vinix&lt;/strong&gt;&lt;/a&gt;: Vinix is an effort to write a modern, fast, and useful operating system in the &lt;a href="https://github.com/vlang/v" rel="noopener noreferrer"&gt;V programming language&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;📝 &lt;a href="https://hardenedbsd.org/article/shawn-webb/2026-09-27/hardenedbsd-august-september-2026-status-report" rel="noopener noreferrer"&gt;&lt;strong&gt;HardenedBSD August / September 2026 Status Report&lt;/strong&gt;&lt;/a&gt;: mostly small modification and bug/security fixes.&lt;/p&gt;

&lt;p&gt;📝 &lt;a href="https://undeadly.org/cgi?action=article;sid=20260927120854" rel="noopener noreferrer"&gt;&lt;strong&gt;OpenBSD-current has moved to version 8.0&lt;/strong&gt;&lt;/a&gt;: openbsd 8.0 will be ready soon.&lt;/p&gt;

&lt;p&gt;📝 &lt;a href="https://undeadly.org/cgi?action=article;sid=20260927115632" rel="noopener noreferrer"&gt;&lt;strong&gt;vmm(4)/vmd(8) gain support for multi-processor VMs&lt;/strong&gt;&lt;/a&gt;: OpenBSD vmm/vmd can now have more than one CPU configured, that's a very good news!&lt;/p&gt;

&lt;p&gt;📝 &lt;a href="https://it-notes.dragas.net/2026/09/28/smartos-the-illumos-way-of-thinking-about-servers/" rel="noopener noreferrer"&gt;&lt;strong&gt;SmartOS: The illumos Way of Thinking About Servers&lt;/strong&gt;&lt;/a&gt;: sunos, illumos and smartos... A good way to introduce them via this article.&lt;/p&gt;

&lt;p&gt;🏗️ &lt;a href="https://github.com/imthenachoman/How-To-Secure-A-Linux-Server" rel="noopener noreferrer"&gt;&lt;strong&gt;How To Secure A Linux Server&lt;/strong&gt;&lt;/a&gt;: An evolving how-to guide for securing a Linux server that, hopefully, also teaches you a little about security and why it matters.&lt;/p&gt;

&lt;p&gt;📝 &lt;a href="https://www.powerpc-notebook.org/2026/09/powerboard-tyche-unveiled-at-pianeta-amiga/" rel="noopener noreferrer"&gt;&lt;strong&gt;Powerboard Tyche unveiled at Pianeta Amiga&lt;/strong&gt;&lt;/a&gt;: Never got an Amiga, never installed AmigaOS, but since I learnt DragonFlyBSD kernel was a mix between FreeBSD and AmigaOS, I always wanted to test it. Another crazy thing is... the community is active! The passion for Amiga seems eternal. Crazy.&lt;/p&gt;

&lt;h1&gt;
  
  
  Security
&lt;/h1&gt;

&lt;p&gt;📝 &lt;a href="https://blog.trailofbits.com/2026/09/18/auditing-in-the-age-of-good-enough-ai/" rel="noopener noreferrer"&gt;&lt;strong&gt;Auditing in the age of (good enough) AI&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;🏗️ &lt;a href="https://github.com/newliver666/apk-reverse" rel="noopener noreferrer"&gt;&lt;strong&gt;apk-reverse&lt;/strong&gt;&lt;/a&gt;: a skill to reverse APK.&lt;/p&gt;

&lt;p&gt;📝 &lt;a href="https://cloud.google.com/blog/topics/threat-intelligence/hardening-code-pipelines-and-ci-cd-infrastructure" rel="noopener noreferrer"&gt;&lt;strong&gt;Proactive Defense: Hardening Code Pipelines and CI/CD Infrastructure&lt;/strong&gt;&lt;/a&gt;: a must read to apply modern protection on CI/CD.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Organizations should mandate a minimum release-age cooldown of seven days before any newly published public package version becomes installable [...] Establishing a strict seven-day buffer provides the open-source ecosystem time to detect and pull poisoned releases before they reach internal builds. [...] All external packages and container images should, wherever possible, route through a centralized internal proxy that caches, inspects, and gates each component.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;📝 &lt;a href="https://blog.qualys.com/vulnerabilities-threat-research/2026/09/28/developer-new-perimeter-supply-chain-cloud-breaches" rel="noopener noreferrer"&gt;&lt;strong&gt;The Developer is the New Perimeter: How Supply Chain Attacks Are Becoming Cloud Breaches&lt;/strong&gt;&lt;/a&gt;: the number of supply chain attacks is growing, and this is another article to remind us to always verify the security of our CI/CD.&lt;/p&gt;

&lt;p&gt;📝 &lt;a href="https://www.404media.co/cops-can-bypass-iphone-automatic-inactivity-reboot-graykey/" rel="noopener noreferrer"&gt;&lt;strong&gt;Cops Can Bypass iPhone’s Automatic Reboot to Get Into Locked Phones, Leaked Video Claims&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Security/Cryptography
&lt;/h1&gt;

&lt;p&gt;📑 &lt;a href="https://eprint.iacr.org/2026/2162.pdf" rel="noopener noreferrer"&gt;&lt;strong&gt;A Survey of Pseudorandom Codes&lt;/strong&gt;&lt;/a&gt;: &lt;/p&gt;

&lt;p&gt;📑 &lt;a href="https://eprint.iacr.org/2026/2145.pdf" rel="noopener noreferrer"&gt;&lt;strong&gt;Fully Anonymous Perfect Secret-Sharing&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;🏗️ &lt;a href="https://github.com/atheonxyz/jolt" rel="noopener noreferrer"&gt;&lt;strong&gt;Jolt&lt;/strong&gt;&lt;/a&gt;: Just One Lookup Table. Jolt is a zkVM (zero-knowledge virtual machine) for RISC-V, built to be the simplest, fastest, and most extensible general-purpose of its kind. A &lt;a href="https://jolt.a16zcrypto.com/" rel="noopener noreferrer"&gt;book&lt;/a&gt; is available.&lt;/p&gt;

&lt;p&gt;📑 &lt;a href="https://eprint.iacr.org/2026/2158.pdf" rel="noopener noreferrer"&gt;&lt;strong&gt;Formally Modeling the Terrapin Attack on SSH&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;📑 &lt;a href="https://eprint.iacr.org/2026/2138.pdf" rel="noopener noreferrer"&gt;&lt;strong&gt;DASH: Distributed Asynchronous Schnorr with High Throughput&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;📑 &lt;a href="https://eprint.iacr.org/2026/2096.pdf" rel="noopener noreferrer"&gt;&lt;strong&gt;Perpetual Encryption&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;📑 &lt;a href="https://eprint.iacr.org/2026/2080.pdf" rel="noopener noreferrer"&gt;&lt;strong&gt;Lightweight Cryptography for Secure UAV Data Integrity Using Ascon-XOF128 and SHAKE128&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;📑 &lt;a href="https://eprint.iacr.org/2026/2131.pdf" rel="noopener noreferrer"&gt;&lt;strong&gt;Forging 1024-bit RSA signatures in nearly SNFS time&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;📑 &lt;a href="https://eprint.iacr.org/2026/2167.pdf" rel="noopener noreferrer"&gt;&lt;strong&gt;New Applications of RSA&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Security/RedTeam
&lt;/h1&gt;

&lt;p&gt;📝 &lt;a href="https://hackers-arise.com/offensive-security-pentesting-office-phones-with-sipvicious/" rel="noopener noreferrer"&gt;&lt;strong&gt;Offensive Security: Pentesting Office Phones with SIPVicious&lt;/strong&gt;&lt;/a&gt;: a post showing a quick demo of &lt;a href="https://github.com/EnableSecurity/sipvicious" rel="noopener noreferrer"&gt;sipvicious&lt;/a&gt; against VoIP local server.&lt;/p&gt;

&lt;h1&gt;
  
  
  Embedded
&lt;/h1&gt;

&lt;p&gt;🏗️ &lt;a href="https://github.com/rems-project/sail" rel="noopener noreferrer"&gt;&lt;strong&gt;Sail architecture definition language&lt;/strong&gt;&lt;/a&gt;: Sail is a language for defining the instruction-set architecture (ISA) semantics of processors: the architectural specification of the behaviour of machine instructions. Sail is an engineer-friendly language, much like earlier vendor pseudocode, but more precisely defined and with tooling to support a wide range of use-cases.&lt;/p&gt;

&lt;p&gt;📝 &lt;a href="https://hackaday.com/2026/09/26/you-can-make-a-microprocessor-thats-all-your-own/" rel="noopener noreferrer"&gt;&lt;strong&gt;You Can Make A Microprocessor That’s All Your Own&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;📝 &lt;a href="https://terminalbytes.com/reverse-engineering-ipod-classic-mikey-chip/" rel="noopener noreferrer"&gt;&lt;strong&gt;Reverse Engineering the iPod Classic's Undocumented Mikey Chip&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Updates/Upgrades
&lt;/h1&gt;

&lt;p&gt;🔄 &lt;a href="https://github.com/benoitc/hackney/releases/tag/4.8.1" rel="noopener noreferrer"&gt;&lt;strong&gt;Hackney 4.8.4&lt;/strong&gt;&lt;/a&gt;: many updates here, from the 4.8.1 to 4.8.4, fixing many bugs. If you are using a previous version, you should probably update it.&lt;/p&gt;

&lt;p&gt;🔄 &lt;a href="https://www.openbsd.org/errata79.html" rel="noopener noreferrer"&gt;&lt;strong&gt;OpenBSD 7.9 Errata&lt;/strong&gt;&lt;/a&gt;: a huge amount of patch (9) to fix security issues on the whole system. &lt;code&gt;ldapd&lt;/code&gt;, &lt;code&gt;nsd&lt;/code&gt; (8 CVEs), &lt;code&gt;unbound&lt;/code&gt; (35 CVEs), &lt;code&gt;iked&lt;/code&gt; and many other issues found on the kernel.&lt;/p&gt;

&lt;p&gt;🔄 &lt;a href="https://www.qubes-os.org/news/2026/10/02/qubes-os-4-3-2-has-been-released/" rel="noopener noreferrer"&gt;&lt;strong&gt;Qubes OS 4.3.2&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Misc
&lt;/h1&gt;

&lt;p&gt;📝 &lt;a href="https://siboehm.com/articles/22/CUDA-MMM" rel="noopener noreferrer"&gt;&lt;strong&gt;How to Optimize a CUDA Matmul Kernel for cuBLAS-like Performance: a Worklog&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;📝 &lt;a href="https://horace.io/brrr_intro.html" rel="noopener noreferrer"&gt;&lt;strong&gt;Making Deep Learning Go Brrrr From First Principles&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;📝 &lt;a href="https://futurism.com/artificial-intelligence/ai-bros-meltdown-feelings" rel="noopener noreferrer"&gt;&lt;strong&gt;AI Bros Are Having a Meltdown Because the Associated Press Stylebook Clarifies That AIs Don’t Have Feelings&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;📝 &lt;a href="https://www.404media.co/someone-torturing-llms-in-a-robot-prison-has-triggered-the-dumbest-debate-in-ai-yet/" rel="noopener noreferrer"&gt;&lt;strong&gt;Someone ‘Torturing’ LLMs in a Robot Prison Has Triggered the Dumbest Debate in AI Yet&lt;/strong&gt;&lt;/a&gt;: Yeah. Crazy right? LLMs are not conscious. Adding a "feature" to feel pain/pleasure in a program does not make it conscious, it adds just another variable in the state, or another way to interpret inputs. This can be called - at best - "LLM moding".&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;AIs are not conscious. &lt;strong&gt;They do not feel, experience, or suffer&lt;/strong&gt;. They do not have innate preferences or underlying motivations. &lt;strong&gt;They are sequence completion engines&lt;/strong&gt;, internally hollow, &lt;strong&gt;designed to follow instructions&lt;/strong&gt;, and accomplish goals set by humans. Unfortunately, there’s a growing chorus of people who argue that AIs could now be, or may soon become, conscious. They argue that AIs may deserve rights and protections similar to those that we provide other conscious beings […] If this is how AI is developed, it will have a disastrous impact on the wellbeing of humanity.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h1&gt;
  
  
  Leaks of the week
&lt;/h1&gt;

&lt;p&gt;📝 &lt;a href="https://frenchbreaches.com/alertes/alaxione-mukgc44jlfsfro727v" rel="noopener noreferrer"&gt;&lt;strong&gt;Alaxione&lt;/strong&gt;&lt;/a&gt;: more than 8.5 millions patients impacted, data from 2010 to 2026. +5 millions phone numbers leaked, +1.4 millions e-mail, +300k social security number.&lt;/p&gt;

&lt;p&gt;📝 &lt;a href="https://frenchbreaches.com/alertes/groupe-kel-orisha-mukzqxqoj9x80n11kl" rel="noopener noreferrer"&gt;&lt;strong&gt;KEL/Orisha&lt;/strong&gt;&lt;/a&gt;: 1.3 million people impacted including +600k e-mail, +600+ phone number, +140k IBAN.&lt;/p&gt;

&lt;p&gt;📝 &lt;a href="https://www.glow.io/blogs/how-ai-agents-exposed-developer-screenshots-from-leading-tech-companies" rel="noopener noreferrer"&gt;&lt;strong&gt;PixelLeak: How AI Agents Exposed Developer Screenshots from Leading Tech Companies&lt;/strong&gt;&lt;/a&gt;: Glow labs identified more than 13k screenshots from 300 organizations (including big companies). Impacted more than 900 repositories and 100k employees. It seems it was mostly skill issue there, and the "AI" were not hardened. Interesting leaks though, because if screenshots can leak, probably other data can be leak as well.&lt;/p&gt;

&lt;p&gt;📝 &lt;a href="https://frenchbreaches.com/alertes/f-d-ration-fran-aise-de-la-randonn-e-ffr-mun6o16r4h0ud0vz18i" rel="noopener noreferrer"&gt;&lt;strong&gt;FFRandonnée&lt;/strong&gt;&lt;/a&gt;: 1.43 millions impacted people, more than 1 million e-mail and 663k phone numbers, with physical address location.&lt;/p&gt;

&lt;p&gt;📝 &lt;a href="https://frenchbreaches.com/alertes/cookson-clal-muomsy4ng1mk25gtxwj" rel="noopener noreferrer"&gt;&lt;strong&gt;Cookson-CLAL&lt;/strong&gt;&lt;/a&gt;: complete credit card information have been leaked. No more information about the number of people impacted though.&lt;/p&gt;

&lt;p&gt;📝 &lt;a href="https://fuitesinfos.fr/article/2026-10-01-vosfactures" rel="noopener noreferrer"&gt;&lt;strong&gt;VosFactures&lt;/strong&gt;&lt;/a&gt;: data leaks on one of the companies in charge of the digital invoices in France. No more information right now, but they have a database with more than 500k companies. Less than 1 month after the official launching of the digital invoices for the companies, one of the "big player" seems to have been impacted by a huge data leaks.&lt;/p&gt;




&lt;p&gt;&lt;iframe class="tweet-embed" id="tweet-2104051150274408672-700" src="https://platform.twitter.com/embed/Tweet.html?id=2104051150274408672"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-2104051150274408672-700');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=2104051150274408672&amp;amp;theme=dark"
  }



&lt;/p&gt;

&lt;p&gt;&lt;a href="https://x.com/rawsalerts/status/2103520617144389928?s=20" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Flcl1vqj8axiy2b8rm8av.png" alt=" " width="598" height="118"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://x.com/tomhacks/status/2103630947883057565?s=20" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fl38xmzhtzftm91zk22my.png" alt=" " width="598" height="398"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://x.com/Qivshi1/status/2103856150592545225?s=20" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fxvtmxz3u8tl5fvvvzcwi.png" alt=" " width="598" height="324"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://x.com/evisdrenova/status/2104052883662717347?s=20" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fxmkqvc994059i11t8erq.png" alt=" " width="598" height="218"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://x.com/Quasilocal/status/2104106284274581643?s=20" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ffxewcf9ivfb3vz30rjlq.png" alt=" " width="598" height="682"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://x.com/banteg/status/2103958454708920387?s=20" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fys5ato4curslczk559fg.png" alt=" " width="598" height="98"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://x.com/CorpAbsurdity/status/2103874469311734112?s=20" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fpow6lmhf3tzrc5bwtxlh.png" alt=" " width="598" height="785"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://x.com/wangzhr4/status/2104220073120702579?s=20" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Frdulc3vadvactqbcsazm.png" alt=" " width="598" height="458"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://x.com/C2IRIS/status/2104231952643428477?s=20" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fr61i7i77n4v2tvow3yg7.png" alt=" " width="598" height="412"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://x.com/jaredLunde/status/2104240208032190768?s=20" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ff0s5baxm2l2pbymb3op2.png" alt=" " width="598" height="160"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://x.com/PoetsLab/status/2104065575580262701?s=20" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fpwtmq2gdyyskmhn679u5.png" alt="AI is malware" width="598" height="98"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://x.com/Mikymigs/status/2104232663968293336?s=20" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fa7xf6clcq18syvn0ya2x.png" alt="AI is cancer" width="598" height="316"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://x.com/jrysana/status/2104441570179404176?s=20" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Freiy8nrtr49nhurpowoy.png" alt=" " width="598" height="100"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fxcmsfmyomvitovcwq3qc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fxcmsfmyomvitovcwq3qc.png" alt=" " width="598" height="238"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://x.com/Polymarket/status/2104499605245251664?s=20" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fjn51inumhx9c17vrs3vu.png" alt=" " width="598" height="138"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://x.com/Polymarket/status/2104719103810224299?s=20" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fdnlc6vd8z2vqf4dex7rn.png" alt="Anthropic’s IPO prospectus reveals a staggering $42,000,000,000.00 net loss in 2025." width="598" height="244"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://x.com/lcamtuf/status/2105023754263028011?s=20" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fwtk7ac8ru4lqpq8cpssc.png" alt=" " width="598" height="118"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://x.com/Grady_Booch/status/2105157423615156439?s=20" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fdd1i71lt6z7i818oxyoc.png" alt=" " width="598" height="118"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://x.com/headzoo/status/2105055215024009662?s=20" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fqrs5cklhd1bsuhu29aoe.png" alt=" " width="598" height="556"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://x.com/mrjasonchoi/status/2105959199452844384?s=20" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fr706o4vbxgwnryudhjz5.png" alt=" " width="598" height="118"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://x.com/shcallaway/status/2106142042405453879?s=20" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fmbkzqedcalh5v73tpeh8.png" alt=" " width="598" height="497"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://x.com/LeoBuilds_/status/2106159384787345556?s=20" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ff37g39oam9frnos18quq.png" alt=" " width="598" height="138"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://x.com/straceX/status/2106374472966295641?s=20" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fcg7askrvwonmhsuahhkc.png" alt=" " width="598" height="138"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fue5f6xw0u722zuw1nqtk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fue5f6xw0u722zuw1nqtk.png" alt=" " width="500" height="620"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fl1ygagmx4xwhe2kr0wha.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fl1ygagmx4xwhe2kr0wha.png" alt=" " width="800" height="794"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F2z3p5texyicdqwl6yi7n.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F2z3p5texyicdqwl6yi7n.png" alt=" " width="510" height="680"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fyc22b3o6fvb0e1yh5qr5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fyc22b3o6fvb0e1yh5qr5.png" alt=" " width="680" height="502"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fghmynwt9m8j9q9xu5krh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fghmynwt9m8j9q9xu5krh.png" alt=" " width="500" height="532"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fcrk08a1uk64jq1w7ibbi.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fcrk08a1uk64jq1w7ibbi.png" alt=" " width="680" height="680"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Frdcssgauqxyhmbkbi5nu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Frdcssgauqxyhmbkbi5nu.png" alt=" " width="586" height="680"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Febwl67dqyedpoxrwjoob.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Febwl67dqyedpoxrwjoob.png" alt=" " width="648" height="679"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F8qmakhnzqzdmplr6i5et.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F8qmakhnzqzdmplr6i5et.png" alt=" " width="612" height="680"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fg3ndxogdb6xtulvrtala.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fg3ndxogdb6xtulvrtala.png" alt=" " width="500" height="500"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;Cover Image by &lt;a href="https://unsplash.com/@kostyadyadyun?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" rel="noopener noreferrer"&gt;Konstantin Dyadyun&lt;/a&gt; on &lt;a href="https://unsplash.com/photos/brown-trees-on-brown-field-during-daytime-50hhiZf9vI0?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" rel="noopener noreferrer"&gt;Unsplash&lt;/a&gt;&lt;/p&gt;

</description>
      <category>weekly</category>
      <category>review</category>
    </item>
    <item>
      <title>Erlang Preprocessor and Elixir Interoperability</title>
      <dc:creator>Mathieu Kerjouan</dc:creator>
      <pubDate>Thu, 01 Oct 2026 10:00:00 +0000</pubDate>
      <link>https://dev.to/niamtokik/erlang-preprocessor-and-elixir-interoperability-4bof</link>
      <guid>https://dev.to/niamtokik/erlang-preprocessor-and-elixir-interoperability-4bof</guid>
      <description>&lt;p&gt;Erlang and Elixir are both running on the BEAM, the Erlang Virtual Machine, designed for long-living and distribute. In most of the case, talking to Erlang modules via Elixir is straightforward, doing the opposite can be a bit challenging though, but it is okay. In few cases though, extracting values from Erlang can become a real problem. The Erlang PreProcessor (&lt;code&gt;epp&lt;/code&gt;) is used to expand Erlang macros before compiling the code, this is a similar feature than one can found in &lt;code&gt;C&lt;/code&gt;, &lt;code&gt;C++&lt;/code&gt; and many other languages. This is a powerful way to avoid code-deduplication, and optimize the execution of the code by directly applying a data-structure instead of a reference. It has many other benefits, but this is not the place here to list them all.&lt;/p&gt;

&lt;h1&gt;
  
  
  Erlang From Code Source to AST
&lt;/h1&gt;

&lt;p&gt;Before doing anything, one should understand a bit how Erlang and the BEAM are working together. The procedure to compile Erlang source code into a binary file is a complex process, but it is possible to have the big picture in few steps.&lt;/p&gt;

&lt;p&gt;Firstly, one need to create a file containing Erlang source code. In fact, this is not mandatory to create a file... but we will see that later. As reminder, an Erlang file prefix is &lt;code&gt;.erl&lt;/code&gt;, and the name of the file must match the name of the module defined in the module itself..&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;cat&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; mod.erl &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;EOF&lt;/span&gt;&lt;span class="sh"&gt;
&lt;/span&gt;&lt;span class="go"&gt;-module(mod).
-compile(export_all).
&lt;/span&gt;&lt;span class="gp"&gt;-define(DATA, &amp;lt;&amp;lt;1,2,3,4,5&amp;gt;&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;)&lt;/span&gt;&lt;span class="nb"&gt;.&lt;/span&gt;
&lt;span class="go"&gt;
&lt;/span&gt;&lt;span class="gp"&gt;f() -&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;?DATA.
&lt;span class="go"&gt;EOF
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The code created is straightforward. A simple module is created exporting all functions, a macro is defined containing a binary, and finally, a function called &lt;code&gt;f/0&lt;/code&gt; is defined, returning the content of the macro.&lt;/p&gt;

&lt;p&gt;The second step is to call the Erlang preprocessor called &lt;a href="https://www.erlang.org/doc/apps/stdlib/epp.html" rel="noopener noreferrer"&gt;&lt;code&gt;epp&lt;/code&gt;&lt;/a&gt; to expand all &lt;a href="https://erlang.org/documentation/doc-4.8.2/doc/extensions/macros.html" rel="noopener noreferrer"&gt;macros&lt;/a&gt; and generate the final source code. The preprocessor will import functions or data-structures from the external libraries (&lt;code&gt;-include&lt;/code&gt; and &lt;code&gt;-include_lib&lt;/code&gt;), expands the macros (&lt;code&gt;-define&lt;/code&gt; and &lt;code&gt;?MACRO&lt;/code&gt;) and can return a list of tokens or the fully expanded source code. This part can easily be seen by using the &lt;code&gt;-P&lt;/code&gt; or &lt;code&gt;-E&lt;/code&gt; flags with the command &lt;a href="https://www.erlang.org/doc/apps/erts/erlc_cmd.html" rel="noopener noreferrer"&gt;&lt;code&gt;erlc&lt;/code&gt;&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;erlc &lt;span class="nt"&gt;-P&lt;/span&gt; mod.erl
&lt;span class="go"&gt;
&lt;/span&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;cat &lt;/span&gt;mod.P
&lt;span class="go"&gt;-file("mod.erl", 1).
-module(mod).
-compile(export_all).

&lt;/span&gt;&lt;span class="gp"&gt;f() -&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="gp"&gt;    &amp;lt;&amp;lt;1,2,3,4,5&amp;gt;&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you can see, the file &lt;code&gt;mod.P&lt;/code&gt; does not have any &lt;code&gt;-define&lt;/code&gt; attribute, and the macro has been expanded. A new attribute &lt;code&gt;-file&lt;/code&gt; has also been added to the source, at the first line. The preprocessor did its job, and the source code can now be tokenized.&lt;/p&gt;

&lt;p&gt;The tokenization procedure can't be seen via a command line, and it will be required to evaluate an Erlang one-line with the &lt;a href="https://www.erlang.org/doc/apps/erts/erl_cmd.html" rel="noopener noreferrer"&gt;&lt;code&gt;erl&lt;/code&gt;&lt;/a&gt; command to have an idea of what's happening.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;erl &lt;span class="nt"&gt;-noshell&lt;/span&gt; &lt;span class="nt"&gt;-eval&lt;/span&gt; &lt;span class="s1"&gt;'
&lt;/span&gt;&lt;span class="go"&gt;  {ok, M}=file:read_file("mod.P"), 
  T = erl_scan:string(binary_to_list(M)),
  io:format("~p~n", [T]),
  init:stop().
'
{ok,[{'-',1},
     {atom,1,file},
     {'(',1},
     {string,1,"mod.erl"},
     {',',1},
     {integer,1,1},
     {')',1},
     {dot,1},
     {'-',3},
     {atom,3,module},
     {'(',3},
     {atom,3,mod},
     {')',3},
     {dot,3},
     {'-',5},
     {atom,5,compile},
     {'(',5},
     {atom,5,export_all},
     {')',5},
     {dot,5},
     {atom,7,f},
     {'(',7},
     {')',7},
&lt;/span&gt;&lt;span class="gp"&gt;     {'-&amp;gt;&lt;/span&gt;&lt;span class="s1"&gt;',7},
&lt;/span&gt;&lt;span class="go"&gt;     {'&amp;lt;&amp;lt;',8},
     {integer,8,1},
     {',',8},
     {integer,8,2},
     {',',8},
     {integer,8,3},
     {',',8},
     {integer,8,4},
     {',',8},
     {integer,8,5},
&lt;/span&gt;&lt;span class="gp"&gt;     {'&amp;gt;&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="s1"&gt;',8},
&lt;/span&gt;&lt;span class="go"&gt;     {dot,8}],
    12}
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here, the &lt;code&gt;mod.P&lt;/code&gt; has been used instead of &lt;code&gt;mod.erl&lt;/code&gt;, because usually, the scanner is scanning the expanded file, not the one containing the macros. This snippet is reading the source code, calling &lt;a href="https://www.erlang.org/doc/apps/stdlib/erl_scan.html#string/3" rel="noopener noreferrer"&gt;&lt;code&gt;erl_scan:string/1&lt;/code&gt;&lt;/a&gt; to scan the tokens, &lt;a href="https://www.erlang.org/doc/apps/stdlib/io.html#t:format/0" rel="noopener noreferrer"&gt;&lt;code&gt;io:format/2&lt;/code&gt;&lt;/a&gt; is called to print the result and finally, the VM is stopped by invoking &lt;a href="https://www.erlang.org/doc/apps/erts/init.html#stop/0" rel="noopener noreferrer"&gt;&lt;code&gt;init:stop/0&lt;/code&gt;&lt;/a&gt;. The result displayed is a list of tokens containing the annotations for each characters.&lt;/p&gt;

&lt;p&gt;A quick note here, &lt;a href="https://www.erlang.org/doc/apps/stdlib/epp.html" rel="noopener noreferrer"&gt;&lt;code&gt;epp&lt;/code&gt;&lt;/a&gt; is usually privileged than &lt;a href="https://www.erlang.org/doc/apps/stdlib/erl_scan.html" rel="noopener noreferrer"&gt;&lt;code&gt;erl_scan&lt;/code&gt;&lt;/a&gt;. The tokens from &lt;a href="https://www.erlang.org/doc/apps/stdlib/epp.html#parse_file/2" rel="noopener noreferrer"&gt;&lt;code&gt;epp:parse_file/2&lt;/code&gt;&lt;/a&gt; are already ready to be used with the parser. Here and example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;erl &lt;span class="nt"&gt;-noshell&lt;/span&gt; &lt;span class="nt"&gt;-eval&lt;/span&gt; &lt;span class="s1"&gt;'
&lt;/span&gt;&lt;span class="go"&gt;  {ok, T} = epp:parse_file("./mod.erl", [{source_name, mod}]),
  io:format("~p~n", [T]),
  init:stop().
'
[{attribute,1,file,{"mod",1}},
 {attribute,1,module,mod},
 {attribute,2,compile,export_all},
 {function,5,f,0,
           [{clause,5,[],[],
                    [{bin,5,
                          [{bin_element,5,{integer,5,1},default,default},
                           {bin_element,5,{integer,5,2},default,default},
                           {bin_element,5,{integer,5,3},default,default},
                           {bin_element,5,{integer,5,4},default,default},
                           {bin_element,5,{integer,5,5},default,default}]}]}]},
 {eof,6}]
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let continue on the previous procedure. The next step before generating the AST (Abstract Syntax Tree) above, is to parse the tokens produced by &lt;a href="https://www.erlang.org/doc/apps/stdlib/erl_scan.html" rel="noopener noreferrer"&gt;&lt;code&gt;erl_scan&lt;/code&gt;&lt;/a&gt;. To do that, &lt;a href="https://www.erlang.org/doc/apps/stdlib/erl_parse.html" rel="noopener noreferrer"&gt;&lt;code&gt;erl_parse&lt;/code&gt;&lt;/a&gt; module is used. The final result can be produced with the &lt;code&gt;-S&lt;/code&gt; flag when calling &lt;a href="https://www.erlang.org/doc/apps/erts/erlc_cmd.html" rel="noopener noreferrer"&gt;&lt;code&gt;erlc&lt;/code&gt;&lt;/a&gt; or by calling &lt;a href="https://www.erlang.org/doc/apps/stdlib/erl_parse.html" rel="noopener noreferrer"&gt;&lt;code&gt;erl_parse&lt;/code&gt;&lt;/a&gt; directly from the shell. Below, the AST produced by &lt;a href="https://www.erlang.org/doc/apps/erts/erlc_cmd.html" rel="noopener noreferrer"&gt;&lt;code&gt;erlc&lt;/code&gt;&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;erlc &lt;span class="nt"&gt;-S&lt;/span&gt; mod.erl
&lt;span class="go"&gt;
&lt;/span&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;cat &lt;/span&gt;mod.S
&lt;span class="go"&gt;{module, mod}.  %% version = 0
{exports, [{f,0},{module_info,0},{module_info,1}]}.
{attributes, []}.
{labels, 7}.
{function, f, 0, 2}.
  {label,1}.
    {line,[{location,"mod.erl",5}]}.
    {func_info,{atom,mod},{atom,f},0}.
  {label,2}.
&lt;/span&gt;&lt;span class="gp"&gt;    {move,{literal,&amp;lt;&amp;lt;1,2,3,4,5&amp;gt;&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;}&lt;/span&gt;,&lt;span class="o"&gt;{&lt;/span&gt;x,0&lt;span class="o"&gt;}}&lt;/span&gt;&lt;span class="nb"&gt;.&lt;/span&gt;
&lt;span class="go"&gt;    return.
{function, module_info, 0, 4}.
  {label,3}.
    {line,[]}.
    {func_info,{atom,mod},{atom,module_info},0}.
  {label,4}.
    {move,{atom,mod},{x,0}}.
    {call_ext_only,1,{extfunc,erlang,get_module_info,1}}.
{function, module_info, 1, 6}.
  {label,5}.
    {line,[]}.
    {func_info,{atom,mod},{atom,module_info},1}.
  {label,6}.
    {move,{x,0},{x,1}}.
    {move,{atom,mod},{x,0}}.
    {call_ext_only,2,{extfunc,erlang,get_module_info,2}}
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The very same result can be done using &lt;a href="https://www.erlang.org/doc/apps/stdlib/erl_parse.html#parse_form/1" rel="noopener noreferrer"&gt;&lt;code&gt;erl_parse:parse_form/1&lt;/code&gt;&lt;/a&gt;, &lt;a href="https://www.erlang.org/doc/apps/stdlib/erl_parse.html#parse_exprs/1" rel="noopener noreferrer"&gt;&lt;code&gt;erl_parse:parse_exprs/1&lt;/code&gt;&lt;/a&gt; or &lt;a href="https://www.erlang.org/doc/apps/stdlib/erl_parse.html#parse_term/1" rel="noopener noreferrer"&gt;&lt;code&gt;erl_parse_term/1&lt;/code&gt;&lt;/a&gt; when the tokens are grouped using the &lt;code&gt;{dot,_}&lt;/code&gt; token.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;erl_parse:parse_form&lt;span class="o"&gt;([&lt;/span&gt;
&lt;span class="go"&gt;  {'-',1},{atom,1,file},{'(',1},
    {string,1,"mod.erl"},{',',1},
  {integer,1,1},{')',1},{dot,1}
]).
{ok,{attribute,1,file,{"mod.erl",1}}}

&lt;/span&gt;&lt;span class="gp"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;erl_parse:parse_form&lt;span class="o"&gt;([&lt;/span&gt;
&lt;span class="gp"&gt;  {atom,7,f}, {'(',7}, {')',7}, {'-&amp;gt;&lt;/span&gt;&lt;span class="s1"&gt;',7},
&lt;/span&gt;&lt;span class="go"&gt;     {'&amp;lt;&amp;lt;',8},
       {integer,8,1}, {',',8},
       {integer,8,2}, {',',8},
       {integer,8,3}, {',',8},
       {integer,8,4}, {',',8},
       {integer,8,5},
&lt;/span&gt;&lt;span class="gp"&gt;     {'&amp;gt;&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="s1"&gt;',8},
&lt;/span&gt;&lt;span class="go"&gt;     {dot,8}
]).
{ok,{function,7,f,0,
              [{clause,7,[],[],
                       [{bin,8,
                             [{bin_element,8,{integer,8,1},default,default},
                              {bin_element,8,{integer,8,2},default,default},
                              {bin_element,8,{integer,8,3},default,default},
                              {bin_element,8,{integer,8,4},default,default},
                              {bin_element,8,{integer,8,5},default,default}]}]}]}}

&lt;/span&gt;&lt;span class="gp"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;erl_parse:parse_term&lt;span class="o"&gt;([&lt;/span&gt;
&lt;span class="go"&gt;  {'&amp;lt;&amp;lt;',8},
    {integer,8,1}, {',',8},
    {integer,8,2}, {',',8},
    {integer,8,3}, {',',8},
    {integer,8,4}, {',',8},
    {integer,8,5},
&lt;/span&gt;&lt;span class="gp"&gt;  {'&amp;gt;&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="s1"&gt;',8},
&lt;/span&gt;&lt;span class="go"&gt;  {dot,8}
]).
&lt;/span&gt;&lt;span class="gp"&gt;{ok,&amp;lt;&amp;lt;1,2,3,4,5&amp;gt;&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;}&lt;/span&gt;
&lt;span class="go"&gt;
&lt;/span&gt;&lt;span class="gp"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;{&lt;/span&gt;ok, File&lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; file:read_file&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"mod.P"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;, 
&lt;span class="go"&gt;  {ok, Tokens, _} = erl_scan:string(
    binary_to_list(File)
  ),
  {_, AST} = lists:foldl(fun
&lt;/span&gt;&lt;span class="gp"&gt;      (D = {dot, _}, {Buf, Acc}) -&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="go"&gt;        {ok, R} = erl_parse:parse_form(
          lists:reverse([D|Buf])
        ),
&lt;/span&gt;&lt;span class="gp"&gt;        {[], [R|Acc]};&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="gp"&gt;      (T, {Buf,Acc}) -&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="go"&gt;        {[T|Buf], Acc}
    end,
    {[], []},
    Tokens
  ),
  lists:reverse(AST).
[{attribute,1,file,{"mod.erl",1}},
 {attribute,3,module,mod},
 {attribute,5,compile,export_all},
 {function,7,f,0,
           [{clause,7,[],[],
                    [{bin,8,
                          [{bin_element,8,{integer,8,1},default,default},
                           {bin_element,8,{integer,8,2},default,default},
                           {bin_element,8,{integer,8,3},default,default},
                           {bin_element,8,{integer,8,4},default,default},
                           {bin_element,8,{integer,8,...},default,default}]}]}]}]
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;More steps are executed after generating the AST, a linter and other checkers can verify the code, but it will be discarded in this part of the article. To finally generate the Erlang bytecode, the file with &lt;code&gt;.beam&lt;/code&gt; prefix, containing the compiled source code, one can call &lt;a href="https://www.erlang.org/doc/apps/erts/erlc_cmd.html" rel="noopener noreferrer"&gt;&lt;code&gt;erlc&lt;/code&gt;&lt;/a&gt; again or use the &lt;a href="https://www.erlang.org/doc/apps/compiler/compile.html#file/1" rel="noopener noreferrer"&gt;&lt;code&gt;compile:file/2&lt;/code&gt;&lt;/a&gt; function when a file is available.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;erlc mod.erl
&lt;span class="go"&gt;
&lt;/span&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;file mod.beam                                                                                                                                                                                                                                                                 
&lt;span class="go"&gt;mod.beam: Erlang BEAM file

&lt;/span&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;hexdump &lt;span class="nt"&gt;-C&lt;/span&gt; mod.beam        
&lt;span class="go"&gt;00000000  46 4f 52 31 00 00 02 50  42 45 41 4d 41 74 55 38  |FOR1...PBEAMAtU8|
00000010  00 00 00 2d ff ff ff fb  30 6d 6f 64 10 66 b0 6d  |...-....0mod.f.m|
00000020  6f 64 75 6c 65 5f 69 6e  66 6f 60 65 72 6c 61 6e  |odule_info`erlan|
00000030  67 f0 67 65 74 5f 6d 6f  64 75 6c 65 5f 69 6e 66  |g.get_module_inf|
00000040  6f 00 00 00 43 6f 64 65  00 00 00 47 00 00 00 10  |o...Code...G....|
00000050  00 00 00 00 00 00 00 b1  00 00 00 07 00 00 00 03  |................|
00000060  01 10 99 10 02 12 22 00  01 20 40 47 00 03 13 01  |......".. @G....|
00000070  30 99 00 02 12 32 00 01  40 40 12 03 4e 10 00 01  |0....2..@@..N...|
00000080  50 99 00 02 12 32 10 01  60 40 03 13 40 12 03 4e  |P....2..`@..@..N|
00000090  20 10 03 00 53 74 72 54  00 00 00 00 49 6d 70 54  | ...StrT....ImpT|
000000a0  00 00 00 1c 00 00 00 02  00 00 00 04 00 00 00 05  |................|
000000b0  00 00 00 01 00 00 00 04  00 00 00 05 00 00 00 02  |................|
000000c0  45 78 70 54 00 00 00 28  00 00 00 03 00 00 00 03  |ExpT...(........|
000000d0  00 00 00 01 00 00 00 06  00 00 00 03 00 00 00 00  |................|
000000e0  00 00 00 04 00 00 00 02  00 00 00 00 00 00 00 02  |................|
000000f0  4c 69 74 54 00 00 00 17  00 00 00 00 00 00 00 01  |LitT............|
00000100  00 00 00 0b 83 6d 00 00  00 05 01 02 03 04 05 00  |.....m..........|
00000110  4d 65 74 61 00 00 00 2d  83 6c 00 00 00 01 68 02  |Meta...-.l....h.|
00000120  77 10 65 6e 61 62 6c 65  64 5f 66 65 61 74 75 72  |w.enabled_featur|
00000130  65 73 6c 00 00 00 01 77  0a 6d 61 79 62 65 5f 65  |esl....w.maybe_e|
00000140  78 70 72 6a 6a 00 00 00  4c 6f 63 54 00 00 00 04  |xprjj...LocT....|
00000150  00 00 00 00 41 74 74 72  00 00 00 27 83 6c 00 00  |....Attr...'.l..|
00000160  00 01 68 02 77 03 76 73  6e 6c 00 00 00 01 6e 10  |..h.w.vsnl....n.|
00000170  00 00 4a 2a a7 c3 41 6d  91 07 cf f0 1d 6d 6e 00  |..J*..Am.....mn.|
00000180  85 6a 6a 00 43 49 6e 66  00 00 00 48 83 6c 00 00  |.jj.CInf...H.l..|
00000190  00 03 68 02 77 07 76 65  72 73 69 6f 6e 6b 00 07  |..h.w.versionk..|
000001a0  39 2e 30 2e 36 2e 31 68  02 77 07 6f 70 74 69 6f  |9.0.6.1h.w.optio|
000001b0  6e 73 6a 68 02 77 06 73  6f 75 72 63 65 6b 00 13  |nsjh.w.sourcek..|
000001c0  2f 74 6d 70 2f 65 72 6c  61 6e 67 2f 6d 6f 64 2e  |/tmp/erlang/mod.|
000001d0  65 72 6c 6a 44 62 67 69  00 00 00 48 83 68 03 77  |erljDbgi...H.h.w|
000001e0  0d 64 65 62 75 67 5f 69  6e 66 6f 5f 76 31 77 11  |.debug_info_v1w.|
000001f0  65 72 6c 5f 61 62 73 74  72 61 63 74 5f 63 6f 64  |erl_abstract_cod|
00000200  65 68 02 77 04 6e 6f 6e  65 6c 00 00 00 01 68 02  |eh.w.nonel....h.|
00000210  77 03 63 77 64 6b 00 0b  2f 74 6d 70 2f 65 72 6c  |w.cwdk../tmp/erl|
00000220  61 6e 67 6a 4c 69 6e 65  00 00 00 15 00 00 00 00  |angjLine........|
00000230  00 00 00 00 00 00 00 03  00 00 00 01 00 00 00 00  |................|
00000240  51 00 00 00 54 79 70 65  00 00 00 0a 00 00 00 03  |Q...Type........|
00000250  00 00 00 01 0f ff 00 00                           |........|
00000258
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you have only the AST instead of a file containing the source code, the &lt;a href="https://www.erlang.org/doc/apps/compiler/compile.html#t:forms/0" rel="noopener noreferrer"&gt;&lt;code&gt;compile:forms/2&lt;/code&gt;&lt;/a&gt; function can be invoked. It will return the name of the module as &lt;code&gt;atom()&lt;/code&gt; and the bytecode.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight erlang"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;ok&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;AST&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;epp&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nf"&gt;parse_file&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"./mod.erl"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[{&lt;/span&gt;&lt;span class="n"&gt;source_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;mod&lt;/span&gt;&lt;span class="p"&gt;}]).&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;ok&lt;/span&gt;&lt;span class="p"&gt;,[{&lt;/span&gt;&lt;span class="n"&gt;attribute&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;file&lt;/span&gt;&lt;span class="p"&gt;,{&lt;/span&gt;&lt;span class="s"&gt;"mod"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;}},&lt;/span&gt;
     &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;attribute&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;module&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;mod&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
     &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;attribute&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;compile&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;export_all&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
     &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;function&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
               &lt;span class="p"&gt;[{&lt;/span&gt;&lt;span class="n"&gt;clause&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,[],[],&lt;/span&gt;
                        &lt;span class="p"&gt;[{&lt;/span&gt;&lt;span class="n"&gt;bin&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                              &lt;span class="p"&gt;[{&lt;/span&gt;&lt;span class="n"&gt;bin_element&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,{&lt;/span&gt;&lt;span class="n"&gt;integer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="n"&gt;default&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;default&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
                               &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;bin_element&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,{&lt;/span&gt;&lt;span class="n"&gt;integer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="n"&gt;default&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;default&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
                               &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;bin_element&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,{&lt;/span&gt;&lt;span class="n"&gt;integer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,...},&lt;/span&gt;&lt;span class="n"&gt;default&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;default&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
                               &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;bin_element&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,{&lt;/span&gt;&lt;span class="n"&gt;integer&lt;/span&gt;&lt;span class="p"&gt;,...},&lt;/span&gt;&lt;span class="n"&gt;default&lt;/span&gt;&lt;span class="p"&gt;,...},&lt;/span&gt;
                               &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;bin_element&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,{...},...}]}]}]},&lt;/span&gt;
     &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;eof&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;}]}&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;ok&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;_&lt;/span&gt;&lt;span class="nv"&gt;Name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;Bytecode&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;compile&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nf"&gt;forms&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;AST&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[]).&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;ok&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;mod&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="mi"&gt;70&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;79&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;82&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;49&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;228&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;66&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;69&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;65&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;77&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;65&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;116&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;85&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;56&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="mi"&gt;45&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;255&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;255&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;255&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;251&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;48&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;109&lt;/span&gt;&lt;span class="p"&gt;,...&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nn"&gt;file&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nf"&gt;write_file&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/tmp/mod.beam"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;Bytecode&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;
&lt;span class="n"&gt;ok&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To be sure the bytecode is working, let open another shell and load it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; /tmp
&lt;span class="go"&gt;
&lt;/span&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;file mod.beam
&lt;span class="go"&gt;mod.beam: Erlang BEAM file

&lt;/span&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;hexdump &lt;span class="nt"&gt;-C&lt;/span&gt; mod.beam
&lt;span class="go"&gt;00000000  46 4f 52 31 00 00 01 e4  42 45 41 4d 41 74 55 38  |FOR1....BEAMAtU8|
00000010  00 00 00 2d ff ff ff fb  30 6d 6f 64 10 66 b0 6d  |...-....0mod.f.m|
00000020  6f 64 75 6c 65 5f 69 6e  66 6f 60 65 72 6c 61 6e  |odule_info`erlan|
00000030  67 f0 67 65 74 5f 6d 6f  64 75 6c 65 5f 69 6e 66  |g.get_module_inf|
00000040  6f 00 00 00 43 6f 64 65  00 00 00 47 00 00 00 10  |o...Code...G....|
00000050  00 00 00 00 00 00 00 b1  00 00 00 07 00 00 00 03  |................|
00000060  01 10 99 10 02 12 22 00  01 20 40 47 00 03 13 01  |......".. @G....|
00000070  30 99 00 02 12 32 00 01  40 40 12 03 4e 10 00 01  |0....2..@@..N...|
00000080  50 99 00 02 12 32 10 01  60 40 03 13 40 12 03 4e  |P....2..`@..@..N|
00000090  20 10 03 00 53 74 72 54  00 00 00 00 49 6d 70 54  | ...StrT....ImpT|
000000a0  00 00 00 1c 00 00 00 02  00 00 00 04 00 00 00 05  |................|
000000b0  00 00 00 01 00 00 00 04  00 00 00 05 00 00 00 02  |................|
000000c0  45 78 70 54 00 00 00 28  00 00 00 03 00 00 00 03  |ExpT...(........|
000000d0  00 00 00 01 00 00 00 06  00 00 00 03 00 00 00 00  |................|
000000e0  00 00 00 04 00 00 00 02  00 00 00 00 00 00 00 02  |................|
000000f0  4c 69 74 54 00 00 00 17  00 00 00 00 00 00 00 01  |LitT............|
00000100  00 00 00 0b 83 6d 00 00  00 05 01 02 03 04 05 00  |.....m..........|
00000110  4c 6f 63 54 00 00 00 04  00 00 00 00 41 74 74 72  |LocT........Attr|
00000120  00 00 00 27 83 6c 00 00  00 01 68 02 77 03 76 73  |...'.l....h.w.vs|
00000130  6e 6c 00 00 00 01 6e 10  00 f2 e4 49 4c e5 8b 35  |nl....n....IL..5|
00000140  3f a4 aa a7 4e af 2c 9c  e1 6a 6a 00 43 49 6e 66  |?...N.,..jj.CInf|
00000150  00 00 00 28 83 6c 00 00  00 02 68 02 77 07 76 65  |...(.l....h.w.ve|
00000160  72 73 69 6f 6e 6b 00 07  39 2e 30 2e 36 2e 31 68  |rsionk..9.0.6.1h|
00000170  02 77 07 6f 70 74 69 6f  6e 73 6a 6a 44 62 67 69  |.w.optionsjjDbgi|
00000180  00 00 00 2e 83 68 03 77  0d 64 65 62 75 67 5f 69  |.....h.w.debug_i|
00000190  6e 66 6f 5f 76 31 77 11  65 72 6c 5f 61 62 73 74  |nfo_v1w.erl_abst|
000001a0  72 61 63 74 5f 63 6f 64  65 68 02 77 04 6e 6f 6e  |ract_codeh.w.non|
000001b0  65 6a 00 00 4c 69 6e 65  00 00 00 1b 00 00 00 00  |ej..Line........|
000001c0  00 00 00 00 00 00 00 03  00 00 00 01 00 00 00 01  |................|
000001d0  12 51 00 03 6d 6f 64 00  54 79 70 65 00 00 00 0a  |.Q..mod.Type....|
000001e0  00 00 00 03 00 00 00 01  0f ff 00 00              |............|
000001ec

&lt;/span&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;erl &lt;span class="nt"&gt;-noshell&lt;/span&gt; &lt;span class="nt"&gt;-eval&lt;/span&gt; &lt;span class="s1"&gt;'
&lt;/span&gt;&lt;span class="go"&gt;  io:format("~p~n", [mod:f()]),
  init:stop().
'
&lt;/span&gt;&lt;span class="gp"&gt;&amp;lt;&amp;lt;1,2,3,4,5&amp;gt;&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is only the tip of the iceberg, the compilation process in Erlang is way more complex than that. In fact, many parts of the pipeline have been discarded. Anyway, the goal of this section was simply to show you how to generate quickly Erlang bytecode. The only interesting step for the goal of the post is the preprocessing one. The idea is to extract Erlang records and macros from Erlang source code and convert them into something usable in Elixir.&lt;/p&gt;

&lt;p&gt;A last note regarding the compilation process. As you probably know, Elixir templating system using macros is really powerful and the abstraction has been really well designed. Did you know Erlang got the same feature years ago? Indeed, it is also possible to compile dynamically the code or alter the AST directly from the virtual machine via &lt;a href="https://www.erlang.org/doc/apps/syntax_tools/merl.html" rel="noopener noreferrer"&gt;&lt;code&gt;merl&lt;/code&gt;&lt;/a&gt; (for Metaprogramming in Erlang). It's way more complex to use than Elixir templates, but it works pretty well.&lt;/p&gt;

&lt;p&gt;BONUS: it is also possible to disassemble the bytecode generated by this process using the &lt;a href="https://www.erlang.org/doc/apps/stdlib/beam_lib.html#chunks/3" rel="noopener noreferrer"&gt;&lt;code&gt;beam_lib:all_chunks/1&lt;/code&gt;&lt;/a&gt; function. It will then give you a better view of the content of a beam file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;erl &lt;span class="nt"&gt;-noshell&lt;/span&gt; &lt;span class="nt"&gt;-eval&lt;/span&gt; &lt;span class="s1"&gt;'
&lt;/span&gt;&lt;span class="go"&gt;  {ok, F} = file:read_file("./mod.beam"),
  {ok,_,Bytes} = beam_lib:all_chunks(F),
  io:format("~p~n", [Bytes]),
  init:stop().
'
[{"AtU8",
  &amp;lt;&amp;lt;255,255,255,251,48,109,111,100,16,102,176,109,111,100,117,108,101,95,105,
    110,102,111,96,101,114,108,97,110,103,240,103,101,116,95,109,111,100,117,
&lt;/span&gt;&lt;span class="gp"&gt;    108,101,95,105,110,102,111&amp;gt;&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;}&lt;/span&gt;,
&lt;span class="go"&gt; {"Code",
  &amp;lt;&amp;lt;0,0,0,16,0,0,0,0,0,0,0,177,0,0,0,7,0,0,0,3,1,16,153,16,2,18,34,0,1,32,64,
    71,0,3,19,1,48,153,0,2,18,50,0,1,64,64,18,3,78,16,0,1,80,153,0,2,18,50,16,
&lt;/span&gt;&lt;span class="gp"&gt;    1,96,64,3,19,64,18,3,78,32,16,3&amp;gt;&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;}&lt;/span&gt;,
&lt;span class="gp"&gt; {"StrT",&amp;lt;&amp;lt;&amp;gt;&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;}&lt;/span&gt;,
&lt;span class="gp"&gt; {"ImpT",&amp;lt;&amp;lt;0,0,0,2,0,0,0,4,0,0,0,5,0,0,0,1,0,0,0,4,0,0,0,5,0,0,0,2&amp;gt;&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;}&lt;/span&gt;,
&lt;span class="go"&gt; {"ExpT",
  &amp;lt;&amp;lt;0,0,0,3,0,0,0,3,0,0,0,1,0,0,0,6,0,0,0,3,0,0,0,0,0,0,0,4,0,0,0,2,0,0,0,0,0,
&lt;/span&gt;&lt;span class="gp"&gt;    0,0,2&amp;gt;&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;}&lt;/span&gt;,
&lt;span class="gp"&gt; {"LitT",&amp;lt;&amp;lt;0,0,0,0,0,0,0,1,0,0,0,11,131,109,0,0,0,5,1,2,3,4,5&amp;gt;&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;}&lt;/span&gt;,
&lt;span class="go"&gt; {"Meta",
  &amp;lt;&amp;lt;131,108,0,0,0,1,104,2,119,16,101,110,97,98,108,101,100,95,102,101,97,116,
    117,114,101,115,108,0,0,0,1,119,10,109,97,121,98,101,95,101,120,112,114,
&lt;/span&gt;&lt;span class="gp"&gt;    106,106&amp;gt;&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;}&lt;/span&gt;,
&lt;span class="gp"&gt; {"LocT",&amp;lt;&amp;lt;0,0,0,0&amp;gt;&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;}&lt;/span&gt;,
&lt;span class="go"&gt; {"Attr",
  &amp;lt;&amp;lt;131,108,0,0,0,1,104,2,119,3,118,115,110,108,0,0,0,1,110,16,0,0,74,42,167,
&lt;/span&gt;&lt;span class="gp"&gt;    195,65,109,145,7,207,240,29,109,110,0,133,106,106&amp;gt;&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;}&lt;/span&gt;,
&lt;span class="go"&gt; {"CInf",
  &amp;lt;&amp;lt;131,108,0,0,0,3,104,2,119,7,118,101,114,115,105,111,110,107,0,7,57,46,48,
    46,54,46,49,104,2,119,7,111,112,116,105,111,110,115,106,104,2,119,6,115,
    111,117,114,99,101,107,0,19,47,116,109,112,47,101,114,108,97,110,103,47,
&lt;/span&gt;&lt;span class="gp"&gt;    109,111,100,46,101,114,108,106&amp;gt;&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;}&lt;/span&gt;,
&lt;span class="go"&gt; {"Dbgi",
  &amp;lt;&amp;lt;131,104,3,119,13,100,101,98,117,103,95,105,110,102,111,95,118,49,119,17,
    101,114,108,95,97,98,115,116,114,97,99,116,95,99,111,100,101,104,2,119,4,
    110,111,110,101,108,0,0,0,1,104,2,119,3,99,119,100,107,0,11,47,116,109,
&lt;/span&gt;&lt;span class="gp"&gt;    112,47,101,114,108,97,110,103,106&amp;gt;&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;}&lt;/span&gt;,
&lt;span class="gp"&gt; {"Line",&amp;lt;&amp;lt;0,0,0,0,0,0,0,0,0,0,0,3,0,0,0,1,0,0,0,0,81&amp;gt;&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;}&lt;/span&gt;,
&lt;span class="gp"&gt; {"Type",&amp;lt;&amp;lt;0,0,0,3,0,0,0,1,15,255&amp;gt;&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;}]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you are even more curious about this bonus, you are invited to read &lt;a href="https://github.com/happi/theBeamBook" rel="noopener noreferrer"&gt;The Beam Book&lt;/a&gt;, you will find there way more information!&lt;/p&gt;

&lt;h1&gt;
  
  
  Erlang Preprocessor (&lt;code&gt;epp&lt;/code&gt;)
&lt;/h1&gt;

&lt;p&gt;The &lt;a href="https://www.erlang.org/doc/apps/stdlib/epp.html" rel="noopener noreferrer"&gt;&lt;code&gt;epp&lt;/code&gt;&lt;/a&gt; module is in charge to parse and expand macros from Erlang source code. Its source code implementation resides in &lt;a href="https://github.com/erlang/otp/blob/master/lib/stdlib/src/epp.erl" rel="noopener noreferrer"&gt;&lt;code&gt;lib/stdlib/epp.erl&lt;/code&gt;&lt;/a&gt;. The content can be intimidating with its 2600 lines of code, but it is not the most complex to read.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;epp&lt;/code&gt; is starting its own server process handling I/O protocols to read data byte by byte with the help of the &lt;a href="https://www.erlang.org/doc/apps/stdlib/io.html#scan_erl_form/3" rel="noopener noreferrer"&gt;&lt;code&gt;io:scan_erl_form/3&lt;/code&gt;&lt;/a&gt;. This server is having its own state updated every time a new correct value is parsed. Let begins our investigation by using the easiest function available to parse and expands macros, &lt;a href="https://www.erlang.org/doc/apps/stdlib/epp.html#parse_file/2" rel="noopener noreferrer"&gt;&lt;code&gt;epp:parse_file/2&lt;/code&gt;&lt;/a&gt;. Ah, before doing that, let improve a bit our test module.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;cat&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; mod2.erl &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;EOF&lt;/span&gt;&lt;span class="sh"&gt;
&lt;/span&gt;&lt;span class="go"&gt;-module(mod2).
-compile(export_all).
-record(test, {field1}).
&lt;/span&gt;&lt;span class="gp"&gt;-define(DATA, &amp;lt;&amp;lt;1,2,3,4,5&amp;gt;&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;)&lt;/span&gt;&lt;span class="nb"&gt;.&lt;/span&gt;
&lt;span class="go"&gt;
&lt;/span&gt;&lt;span class="gp"&gt;f() -&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;?DATA
&lt;span class="go"&gt;EOF
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;An Erlang record called &lt;code&gt;test&lt;/code&gt; has been added. It was missing from the previous module.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;{&lt;/span&gt;ok, AST&lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; epp:parse_file&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"mod2.erl"&lt;/span&gt;, &lt;span class="o"&gt;[])&lt;/span&gt;&lt;span class="nb"&gt;.&lt;/span&gt;
&lt;span class="go"&gt;{ok,[{attribute,1,file,{"mod2.erl",1}},
     {attribute,1,module,mod2},
     {attribute,2,compile,export_all},
     {attribute,3,record,
                {test,[{record_field,3,{atom,3,field1}}]}},
     {function,6,f,0,
               [{clause,6,[],[],
                        [{bin,6,
                              [{bin_element,6,{integer,6,1},default,default},
                               {bin_element,6,{integer,6,...},default,default},
                               {bin_element,6,{integer,...},default,...},
                               {bin_element,6,{...},...},
                               {bin_element,6,...}]}]}]},
     {eof,7}]}
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you can see, a new attribute for the record is present, containing its description but there is no trace of the &lt;code&gt;DATA&lt;/code&gt; macro defined (again). This is because &lt;code&gt;epp&lt;/code&gt; returns the fully expand source code. Great, but those macros should be stored somewhere... right? Indeed, they are stored inside the &lt;a href="https://github.com/erlang/otp/blob/master/lib/stdlib/src/epp.erl#L276" rel="noopener noreferrer"&gt;&lt;code&gt;#epp{}&lt;/code&gt; record&lt;/a&gt; present in the epp server's state. Unfortunately, this server is not directly available when using &lt;a href="https://www.erlang.org/doc/apps/stdlib/epp.html#parse_file/2" rel="noopener noreferrer"&gt;&lt;code&gt;epp:parse_file/2&lt;/code&gt;&lt;/a&gt;, and &lt;a href="https://www.erlang.org/doc/apps/stdlib/epp.html#open/1" rel="noopener noreferrer"&gt;&lt;code&gt;epp:open/1&lt;/code&gt;&lt;/a&gt; must be used instead. This function is opening a file using I/O protocols and returns a process identifier to extract all tokens step by steps.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;{&lt;/span&gt;ok, EppProcess&lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; epp:open&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"mod2.erl"&lt;/span&gt;, &lt;span class="o"&gt;[]&lt;/span&gt;, &lt;span class="o"&gt;[])&lt;/span&gt;&lt;span class="nb"&gt;.&lt;/span&gt;
&lt;span class="gp"&gt;{ok,&amp;lt;0.175.0&amp;gt;&lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To avoid repetitive task, let create &lt;code&gt;EppRead/2&lt;/code&gt; lambda function to incrementally read the tokens from the epp server. Every time &lt;a href="https://www.erlang.org/doc/apps/stdlib/epp.html#scan_erl_form/1" rel="noopener noreferrer"&gt;&lt;code&gt;epp:scan_erl_form/1&lt;/code&gt;&lt;/a&gt; is called, the epp server should send a message containing its position in the file. When it reaches the end of the file, it sends &lt;code&gt;{eof, Line}&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;EppRead &lt;span class="o"&gt;=&lt;/span&gt; fun EppRead&lt;span class="o"&gt;(&lt;/span&gt;Pid, Buffer&lt;span class="o"&gt;)&lt;/span&gt; -&amp;gt;
&lt;span class="go"&gt;  case epp:scan_erl_form(Pid) of
&lt;/span&gt;&lt;span class="gp"&gt;    {ok, T} -&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;EppRead&lt;span class="o"&gt;(&lt;/span&gt;Pid, Buffer ++ T&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="gp"&gt;    {eof, _} -&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;{&lt;/span&gt;ok, Buffer&lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="go"&gt;  end
end.
&lt;/span&gt;&lt;span class="gp"&gt;#&lt;/span&gt;Fun&amp;lt;erl_eval.18.113135111&amp;gt;
&lt;span class="go"&gt;
&lt;/span&gt;&lt;span class="gp"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;{&lt;/span&gt;ok, Forms&lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; EppRead&lt;span class="o"&gt;(&lt;/span&gt;EppProcess, &lt;span class="o"&gt;[])&lt;/span&gt;&lt;span class="nb"&gt;.&lt;/span&gt;
&lt;span class="go"&gt;[{'-',1},
 {atom,1,file},
 {'(',1},
 {string,1,"mod.erl"},
 {',',1},
 {integer,1,1},
 {')',1},
 {dot,1},
 {'-',1},
 {atom,1,module},
 {'(',1},
 {atom,1,mod},
 {')',1},
 {dot,1},
 {'-',2},
 {atom,2,compile},
 {'(',2},
 {atom,2,export_all},
 {')',2},
 {dot,2},
 {atom,5,f},
 {'(',5},
 {')',5},
&lt;/span&gt;&lt;span class="gp"&gt; {'-&amp;gt;&lt;/span&gt;&lt;span class="s1"&gt;',5},
&lt;/span&gt;&lt;span class="go"&gt; {'&amp;lt;&amp;lt;',5},
 {integer,5,1},
 {',',5},
 {integer,...},
 {...}|...]
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Great, the tokens are available, it means it works correctly without any syntax errors. How to extract the process state? The &lt;a href="https://www.erlang.org/doc/apps/stdlib/epp.html" rel="noopener noreferrer"&gt;&lt;code&gt;epp&lt;/code&gt;&lt;/a&gt; server does not support &lt;code&gt;sys&lt;/code&gt; patterns, and using &lt;a href="https://www.erlang.org/doc/apps/stdlib/sys.html#get_state/1" rel="noopener noreferrer"&gt;&lt;code&gt;sys:get_state/1&lt;/code&gt;&lt;/a&gt; will simply froze the current process. If you read the source code of the module, you will find the undocumented &lt;a href="https://github.com/erlang/otp/blob/master/lib/stdlib/src/epp.erl#L456" rel="noopener noreferrer"&gt;&lt;code&gt;macro_defs/1&lt;/code&gt;&lt;/a&gt; function. It sends a message to an &lt;a href="https://www.erlang.org/doc/apps/stdlib/epp.html" rel="noopener noreferrer"&gt;&lt;code&gt;epp&lt;/code&gt;&lt;/a&gt; server and should return the list of macros stored in &lt;a href="https://github.com/erlang/otp/blob/master/lib/stdlib/src/epp.erl#L1172" rel="noopener noreferrer"&gt;server's state&lt;/a&gt;. Let reimplement this function ourselves.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;GetMacros &lt;span class="o"&gt;=&lt;/span&gt; fun &lt;span class="o"&gt;(&lt;/span&gt;Pid&lt;span class="o"&gt;)&lt;/span&gt; -&amp;gt;
&lt;span class="go"&gt;  Pid ! {epp_request, self(), macro_defs},
  receive
&lt;/span&gt;&lt;span class="gp"&gt;    {epp_reply, Pid, Macros} -&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;Macros
&lt;span class="go"&gt;  after
&lt;/span&gt;&lt;span class="gp"&gt;    1000 -&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;error
&lt;span class="go"&gt;  end
end.
&lt;/span&gt;&lt;span class="gp"&gt;#&lt;/span&gt;Fun&amp;lt;erl_eval.42.113135111&amp;gt;
&lt;span class="go"&gt;
&lt;/span&gt;&lt;span class="gp"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;GetMacros&lt;span class="o"&gt;(&lt;/span&gt;EppProcess&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="nb"&gt;.&lt;/span&gt;
&lt;span class="go"&gt;[{{atom,'FEATURE_ENABLED'},[{1,{['X'],[{atom,1,false}]}}]},
 {{atom,'FEATURE_AVAILABLE'},
  [{1,
    {['X'],
     [{'(',1},
      {'(',1},
      {var,1,'X'},
      {')',1},
      {'==',1},
      {atom,1,maybe_expr},
      {')',1}]}}]},
 {{atom,'OTP_RELEASE'},{none,[{integer,1,28}]}},
 {{atom,'MACHINE'},{none,[{atom,1,'BEAM'}]}},
 {{atom,'LINE'},{none,[{integer,1,1}]}},
 {{atom,'FILE'},{none,[{string,1,"mod2.erl"}]}},
 {{atom,'MODULE'},{none,[{atom,1,mod2}]}},
 {{atom,'MODULE_STRING'},{none,[{string,1,"mod2"}]}},
 {{atom,'BASE_MODULE'},undefined},
 {{atom,'BASE_MODULE_STRING'},undefined},
 {{atom,'FUNCTION_ARITY'},undefined},
 {{atom,'FUNCTION_NAME'},undefined},
 {{atom,'BEAM'},{none,[{atom,1,true}]}},
 {{atom,'DATA'},
  [{none,{none,[{'&amp;lt;&amp;lt;',4},
                {integer,4,1},
                {',',4},
                {integer,4,2},
                {',',4},
                {integer,4,...},
                {',',...},
                {...}|...]}}]}]
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Indeed, all the macros have been returned, including the one defined by &lt;a href="https://www.erlang.org/doc/apps/stdlib/epp.html" rel="noopener noreferrer"&gt;&lt;code&gt;epp&lt;/code&gt;&lt;/a&gt;. The format of the macros stored here can be described below&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight erlang"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;atom&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;MacroName&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nv"&gt;MacroArity&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;MacroTermOrExprs&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The name of the macro is defined in &lt;code&gt;MacroName&lt;/code&gt; as a &lt;code&gt;charlist()&lt;/code&gt; type. The next part is the definition of the macro where:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;MacroArity&lt;/code&gt; is the arity of the macro. If the macro does not have argument, it is set to &lt;code&gt;none&lt;/code&gt;, else, it is set to a strictly positive integer greater than 0.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;MacroTermOrExprs&lt;/code&gt; is the content of the macro, it can contain an Erlang term or an expression, and can also contain a variable previously defined in the argument part.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Because &lt;code&gt;mod2.erl&lt;/code&gt; does not define any macros with arguments, let creates one to see how it is represented.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight erlang"&gt;&lt;code&gt;&lt;span class="p"&gt;-&lt;/span&gt;&lt;span class="ni"&gt;define&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;DYN&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;X&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;Y&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;Z&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="nv"&gt;X&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nv"&gt;Y&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nv"&gt;Z&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This macro when extracted looks like the Erlang term below.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight erlang"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;atom&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;'DYN'&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;{[&lt;/span&gt;&lt;span class="n"&gt;'X'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;'Y'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;'Z'&lt;/span&gt;&lt;span class="p"&gt;],[&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;'X'&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;'+'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;'Y'&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;'+'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;'Z'&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;]}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you can see, this is not so different than the rest of AST, the arguments defined in the macro are expanded in the body of the macro  using the token &lt;code&gt;{var, Line, ArgumentName}&lt;/code&gt;. Finally, don't forget to close the file to avoid file descriptor exception at the end of this experiment.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;epp:close&lt;span class="o"&gt;(&lt;/span&gt;EppServer&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="nb"&gt;.&lt;/span&gt;
&lt;span class="go"&gt;ok
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's great, it is now possible to extract both records and macros, one from the AST, the other one directly from the preprocessor state. Let find a way to deal with that in Elixir.&lt;/p&gt;

&lt;h1&gt;
  
  
  Erlang Records in Elixir
&lt;/h1&gt;

&lt;p&gt;Elixir already has an interface to deal with Erlang records called &lt;a href="https://elixir.hexdocs.pm/Record.html" rel="noopener noreferrer"&gt;&lt;code&gt;Record&lt;/code&gt;&lt;/a&gt;. This is working well in most of the case, let just have a look on it. First, a record can only created inside a module, because it uses Elixir meta-programming feature with macros and templates.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;cat&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; r.ex &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;EOF&lt;/span&gt;&lt;span class="sh"&gt;
&lt;/span&gt;&lt;span class="go"&gt;defmodule R do
  require Record

  Record.defrecord(:test, data: "test")
end
EOF
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;iex&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;c&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"r.ex"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="go"&gt;[R]

&lt;/span&gt;&lt;span class="gp"&gt;iex&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;import R
&lt;span class="go"&gt;R

&lt;/span&gt;&lt;span class="gp"&gt;iex&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;R.test&lt;span class="o"&gt;()&lt;/span&gt;
&lt;span class="go"&gt;{:test, "test"}

&lt;/span&gt;&lt;span class="gp"&gt;iex&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;R.test&lt;span class="o"&gt;(&lt;/span&gt;:data&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="go"&gt;1

&lt;/span&gt;&lt;span class="gp"&gt;iex&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;R.test&lt;span class="o"&gt;()&lt;/span&gt; |&amp;gt; R.test&lt;span class="o"&gt;(&lt;/span&gt;data: &lt;span class="s2"&gt;"updated"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="go"&gt;{:test, "updated"}
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Okay, great, but now, let check a real-world Erlang records from some very used modules, like &lt;a href="https://www.erlang.org/doc/apps/public_key/public_key.html" rel="noopener noreferrer"&gt;&lt;code&gt;public_key&lt;/code&gt;&lt;/a&gt;. Most if not all records are defined in &lt;a href="https://github.com/erlang/otp/blob/master/lib/public_key/include/public_key.hrl" rel="noopener noreferrer"&gt;&lt;code&gt;public_key/include/public_key.hrl&lt;/code&gt;&lt;/a&gt;. The first one you will encounter is the &lt;code&gt;RSAPublicKey&lt;/code&gt; record.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight erlang"&gt;&lt;code&gt;&lt;span class="p"&gt;-&lt;/span&gt;&lt;span class="ni"&gt;record&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;'RSAPublicKey'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;modulus&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;publicExponent&lt;/span&gt;
 &lt;span class="p"&gt;}).&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Can you see the problem here? When using the Elixir Record module, it creates a function to simulate the behavior of the record, but here, the record identifier is a word starting with an uppercase character. It is not possible to create a function with an uppercase character in Elixir. Just to be sure, a new module containing a function starting with an uppercase letter can be created.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;cat&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; up.ex &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;EOF&lt;/span&gt;&lt;span class="sh"&gt;
&lt;/span&gt;&lt;span class="go"&gt;defmodule Up do
  def TestFunction(), do: 1
end
EOF
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;iex&amp;gt; c("up.ex")
== Compilation error in file up.ex ==
** (SyntaxError) invalid syntax found on up.ex:2:19:
    error: unexpected ( after alias TestFunction. Function names and identifiers in Elixir start with lowercase characters or underscore. For example:

        hello_world()
        _starting_with_underscore()
        numb3rs_are_allowed()
        may_finish_with_question_mark?()
        may_finish_with_exclamation_mark!()

    Unexpected token: (
    │
  2 │   def TestFunction(), do: 1
    │                   ^
    │
    └─ up.ex:2:19
    (elixir 1.19.5) lib/kernel/parallel_compiler.ex:530: anonymous fn/5 in Kernel.ParallelCompiler.spawn_workers/8
** (CompileError) compile error
    (iex 1.19.5) lib/iex/helpers.ex:245: IEx.Helpers.c/2
    iex:15: (file)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Well, you would probably say something like "not a problem, if it's the only record...", I stop you right there. More than 150 records are using this format in the &lt;code&gt;public_key&lt;/code&gt; module. Defining 150+ functions is annoying, but because they are all following the same pattern, macros or module templates can be used.&lt;/p&gt;

&lt;p&gt;This issue can be solved in many different ways, the first one is to create a function &lt;code&gt;record/1&lt;/code&gt; where the first argument will contain the record name as an &lt;code&gt;atom()&lt;/code&gt; starting with an uppercase. Every new record can be added like that.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;iex&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;R.record&lt;span class="o"&gt;(&lt;/span&gt;:RSAPrivateKey&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="go"&gt;{:RSAPrivateKey, :undefined, :undefined}

&lt;/span&gt;&lt;span class="gp"&gt;iex&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;R.record&lt;span class="o"&gt;(&lt;/span&gt;:RSAPrivateKey, modulus: 3, publicExponent: 111&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="go"&gt;{:RSAPrivateKey, 3, 111}

&lt;/span&gt;&lt;span class="gp"&gt;iex&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;R.record&lt;span class="o"&gt;(&lt;/span&gt;:RSAPrivateKey&lt;span class="o"&gt;)&lt;/span&gt; |&amp;gt; R.record&lt;span class="o"&gt;(&lt;/span&gt;:modulus, 3&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="go"&gt;{:RSAPrivateKey, 3, :undefined}
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The second solution is the one I prefer. Instead of creating a function containing all record in one place, why not creating a module containing an Elixir struct to represent the record itself? Well, let create the module in charge of that. It will be called &lt;a href="https://github.com/niamtokik/preprocessing" rel="noopener noreferrer"&gt;&lt;code&gt;Preprocessing&lt;/code&gt;&lt;/a&gt; and the sources are already available on github&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="k"&gt;defmodule&lt;/span&gt; &lt;span class="no"&gt;Preprocessing&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Record&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Listing the available records from an Erlang file is one of the main requirement. To do that, it is possible to mix 2 functions, &lt;code&gt;:code.lib_dir/1&lt;/code&gt; to get the path of the module, and &lt;code&gt;:epp.parse_file/2&lt;/code&gt; to parse the Erlang source code. The &lt;code&gt;list_records/3&lt;/code&gt; function returns all the record identifier as &lt;code&gt;[atom()]&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;list_records&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;module&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;filepath&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;opts&lt;/span&gt; &lt;span class="p"&gt;\\&lt;/span&gt; &lt;span class="p"&gt;%{})&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="ss"&gt;:code&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;lib_dir&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;module&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:error&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;reason&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:error&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;reason&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="n"&gt;path&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
        &lt;span class="n"&gt;target&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Path&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;join&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;filepath&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
        &lt;span class="n"&gt;list_records2&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;module&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;target&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;opts&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;defp&lt;/span&gt; &lt;span class="n"&gt;list_records2&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;module&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;target&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;opts&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;source_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Map&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;opts&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:source_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;module&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;with&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="no"&gt;File&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;exists?&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;target&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
         &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:ok&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tokens&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="ss"&gt;:epp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;parse_file&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;target&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;source_name:&lt;/span&gt; &lt;span class="n"&gt;source_name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;do&lt;/span&gt;
      &lt;span class="n"&gt;for&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:attribute&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:record&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;record_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;}}&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="n"&gt;tokens&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;record_name&lt;/span&gt;
    &lt;span class="k"&gt;else&lt;/span&gt;
      &lt;span class="no"&gt;false&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:error&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:path&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;
      &lt;span class="n"&gt;other&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;other&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, a way to extract the records is required as well. In this case, the &lt;code&gt;Record.extract/2&lt;/code&gt; can be reused without, it has been created for that.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;extract&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;module&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;filepath&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;record&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;target&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Path&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;join&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="no"&gt;Atom&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;to_string&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;module&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;filepath&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
    &lt;span class="no"&gt;Record&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;extract&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;record&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;from_lib:&lt;/span&gt; &lt;span class="n"&gt;target&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Finally, the module template can be created with the help of the special macro called &lt;code&gt;__using__/1&lt;/code&gt;. When used on another module, it will generate all the required functions to deal with the imported record.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="k"&gt;defmacro&lt;/span&gt; &lt;span class="n"&gt;__using__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;opts&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;record_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Keyword&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;opts&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:record_id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;module&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Keyword&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;opts&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:module&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;filepath&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Keyword&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;opts&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:filepath&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;fields&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;extract&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;module&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;filepath&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;record_id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;keys&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;for&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;k&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="n"&gt;fields&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;k&lt;/span&gt;
    &lt;span class="n"&gt;values&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;for&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="n"&gt;fields&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;v&lt;/span&gt;
    &lt;span class="n"&gt;tuple&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:record_id&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;++&lt;/span&gt; &lt;span class="n"&gt;values&lt;/span&gt;
      &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;List&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;to_tuple&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
      &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Macro&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;escape&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;record_size&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;length&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fields&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;

    &lt;span class="kn"&gt;quote&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
      &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="no"&gt;Preprocessing&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Record&lt;/span&gt;

      &lt;span class="k"&gt;defstruct&lt;/span&gt; &lt;span class="kn"&gt;unquote&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fields&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

      &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kn"&gt;unquote&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;record_id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

      &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;fields&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kn"&gt;unquote&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fields&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

      &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;keys&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kn"&gt;unquote&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;keys&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

      &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;tuple&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kn"&gt;unquote&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tuple&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

      &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;struct&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;%&lt;/span&gt;&lt;span class="bp"&gt;__MODULE__&lt;/span&gt;&lt;span class="p"&gt;{}&lt;/span&gt;

      &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;is_valid?&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;record&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
        &lt;span class="k"&gt;cond&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; 
          &lt;span class="n"&gt;is_tuple&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;record&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; 
            &lt;span class="ss"&gt;:erlang&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;record&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="kn"&gt;unquote&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;record_size&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; 
            &lt;span class="ss"&gt;:erlang&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;element&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;record&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="kn"&gt;unquote&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;record_id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;
          &lt;span class="no"&gt;true&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;false&lt;/span&gt;
        &lt;span class="k"&gt;end&lt;/span&gt;
      &lt;span class="k"&gt;end&lt;/span&gt;

      &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;convert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;struct&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;%&lt;/span&gt;&lt;span class="bp"&gt;__MODULE__&lt;/span&gt;&lt;span class="p"&gt;{})&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
        &lt;span class="n"&gt;map&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Map&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;from_struct&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;struct&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:ok&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;Enum&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;reduce&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fields&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="n"&gt;k&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="n"&gt;acc&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; 
            &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="no"&gt;Map&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;map&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;k&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;acc&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
          &lt;span class="k"&gt;end&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
          &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Enum&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;reverse&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
          &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;xs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kn"&gt;unquote&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;record_id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;xs&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="k"&gt;end&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
          &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;List&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;to_tuple&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="k"&gt;end&lt;/span&gt;
      &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;convert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;record&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;when&lt;/span&gt; &lt;span class="n"&gt;is_tuple&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;record&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;is_valid?&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;record&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
          &lt;span class="n"&gt;record_list&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
            &lt;span class="no"&gt;Tuple&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;to_list&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;record&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Enum&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;drop&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

          &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:ok&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;keys&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
            &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Enum&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;zip&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;record_list&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Enum&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;reduce&lt;/span&gt;&lt;span class="p"&gt;(%&lt;/span&gt;&lt;span class="bp"&gt;__MODULE__&lt;/span&gt;&lt;span class="p"&gt;{},&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="n"&gt;k&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="n"&gt;acc&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; 
              &lt;span class="no"&gt;Map&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;put&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;acc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;k&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="k"&gt;end&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
          &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="k"&gt;else&lt;/span&gt;
          &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:error&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:invalid_tuple&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="k"&gt;end&lt;/span&gt;
      &lt;span class="k"&gt;end&lt;/span&gt;
      &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;convert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:error&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:invalid_term&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

      &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;convert!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;record&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
        &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="n"&gt;convert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;record&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
          &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:ok&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;
          &lt;span class="n"&gt;other&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="n"&gt;other&lt;/span&gt;
        &lt;span class="k"&gt;end&lt;/span&gt;
      &lt;span class="k"&gt;end&lt;/span&gt;

    &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Great! Let creates our first interface to an existing record. &lt;code&gt;#RSAPublicKey{}&lt;/code&gt; from the &lt;code&gt;public_key&lt;/code&gt; module is a good target.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="k"&gt;defmodule&lt;/span&gt; &lt;span class="no"&gt;Preprocessing&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;PublicKey&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;RSAPublicKey&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="no"&gt;Preprocessing&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Record&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="ss"&gt;record_id:&lt;/span&gt; &lt;span class="ss"&gt;:RSAPublicKey&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="ss"&gt;module:&lt;/span&gt; &lt;span class="ss"&gt;:public_key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="ss"&gt;filepath:&lt;/span&gt; &lt;span class="s2"&gt;"include/public_key.hrl"&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's all. The project can now be recompile and it will be possible to test our new module.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;iex&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;alias &lt;/span&gt;Preprocessing.PublicKey.RSAPublicKey
&lt;span class="go"&gt;Preprocessing.PublicKey.RSAPublicKey

&lt;/span&gt;&lt;span class="gp"&gt;iex&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;RSAPublicKey.is_valid?&lt;span class="o"&gt;({&lt;/span&gt;:RSAPublicKey, :undefined, :undefined&lt;span class="o"&gt;})&lt;/span&gt;
&lt;span class="go"&gt;true

&lt;/span&gt;&lt;span class="gp"&gt;iex&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;RSAPublicKey.is_valid?&lt;span class="o"&gt;({&lt;/span&gt;:RSAPublicKey&lt;span class="o"&gt;})&lt;/span&gt;
&lt;span class="go"&gt;false

&lt;/span&gt;&lt;span class="gp"&gt;iex&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;RSAPublicKey.keys&lt;span class="o"&gt;()&lt;/span&gt;
&lt;span class="go"&gt;[:modulus, :publicExponent]

&lt;/span&gt;&lt;span class="gp"&gt;iex&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;RSAPublicKey.struct&lt;span class="o"&gt;()&lt;/span&gt;
&lt;span class="go"&gt;%PublicKey.RSAPublicKey{
  modulus: :undefined,
  publicExponent: :undefined
}

&lt;/span&gt;&lt;span class="gp"&gt;iex&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;%RSAPublicKey&lt;span class="o"&gt;{}&lt;/span&gt;
&lt;span class="go"&gt;%RSAPublicKey{
  modulus: :undefined,
  publicExponent: :undefined
}

&lt;/span&gt;&lt;span class="gp"&gt;iex&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;RSAPublicKey.convert&lt;span class="o"&gt;(&lt;/span&gt;%RSAPublicKey&lt;span class="o"&gt;{})&lt;/span&gt;
&lt;span class="go"&gt;{:RSAPublicKey, :undefined, :undefined}

&lt;/span&gt;&lt;span class="gp"&gt;iex&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;RSAPublicKey.convert&lt;span class="o"&gt;({&lt;/span&gt;:RSAPublicKey, :undefined, :undefined&lt;span class="o"&gt;})&lt;/span&gt;
&lt;span class="go"&gt;%PublicKey.RSAPublicKey{
  modulus: :undefined,
  publicExponent: :undefined
}
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This module is not perfect though. For example, a function to valid and convert the data correctly from the Elixir struct to the record and vice verse is required. At this time, the developer is in charge of creating the interface for this process. This solution still looks better than the first one. Every new records are treated as individual data-structure defined in their own containers with their own functions. &lt;/p&gt;

&lt;h1&gt;
  
  
  Erlang Macros Definition in Elixir
&lt;/h1&gt;

&lt;p&gt;The Erlang preprocessor macros are not so different than the Erlang records, except when it comes to their arity. In this implementation, only static macros will be supported, but it should not be too complex to implement something with arguments support. Anyway, in a previous section, we saw the macros where stored in the &lt;a href="https://www.erlang.org/doc/apps/stdlib/epp.html" rel="noopener noreferrer"&gt;&lt;code&gt;epp&lt;/code&gt;&lt;/a&gt; server process state and must be extracted with an undocumented function from the &lt;a href="https://www.erlang.org/doc/apps/stdlib/epp.html" rel="noopener noreferrer"&gt;&lt;code&gt;epp&lt;/code&gt;&lt;/a&gt; module. In fact, most of the hard work is already done, now, we need a way to integrate them in Elixir.&lt;/p&gt;

&lt;p&gt;Static macros are basically made of a key and a value. Why not converting them as &lt;a href="https://elixir.hexdocs.pm/Map.html" rel="noopener noreferrer"&gt;&lt;code&gt;Map.t()&lt;/code&gt;&lt;/a&gt; or &lt;a href="https://elixir.hexdocs.pm/Keyword.html" rel="noopener noreferrer"&gt;&lt;code&gt;Keyword.t()&lt;/code&gt;&lt;/a&gt; in this case? In fact, a macro with the same name than another one present below will overwrite the value of the previous definition. This means it's impossible to have a naming conflict, perfect for a &lt;a href="https://elixir.hexdocs.pm/Map.html" rel="noopener noreferrer"&gt;&lt;code&gt;Map.t()&lt;/code&gt;&lt;/a&gt;. First, let creates a new module called &lt;code&gt;Preprocessing.Macros&lt;/code&gt;, it will contain all the functions required to extract and convert macros, but also a template to include them inside another module.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="k"&gt;defmodule&lt;/span&gt; &lt;span class="no"&gt;Preprocessing&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Macros&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;definitions/2&lt;/code&gt; functions is the only one exported from the module, and will return the converted list of macros as &lt;code&gt;Map.t()&lt;/code&gt;. This function is used to generate the template but also to find all the macros from a specific module while developing.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;definitions&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;module&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;filepath&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;with&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:ok&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;pid&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="n"&gt;open_file&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;module&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;filepath&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
      &lt;span class="ss"&gt;:ok&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="n"&gt;definitions_loop&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pid&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:ok&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;macros&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="n"&gt;definitions_macros&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pid&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;do&lt;/span&gt;
      &lt;span class="n"&gt;convert_macros&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;macros&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[])&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;All the remaining functions are not exposed to the rest of the application, and are being used to deal with every step of the conversion. The &lt;code&gt;open_file/2&lt;/code&gt; function is a wrapper around &lt;a href="https://www.erlang.org/doc/apps/stdlib/epp.html#open/1" rel="noopener noreferrer"&gt;&lt;code&gt;:epp.open/2&lt;/code&gt;&lt;/a&gt;, checking if a path is available and returning the process id of the &lt;code&gt;epp&lt;/code&gt; server.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;  &lt;span class="k"&gt;defp&lt;/span&gt; &lt;span class="n"&gt;open_file&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;module&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;filepath&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="ss"&gt;:code&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;lib_dir&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;module&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:error&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;reason&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:error&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;reason&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="n"&gt;path&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
        &lt;span class="no"&gt;Path&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;join&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;filepath&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
          &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;String&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;to_charlist&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
          &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="ss"&gt;:epp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;open&lt;/span&gt;&lt;span class="p"&gt;([],&lt;/span&gt; &lt;span class="p"&gt;[])&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;definitions_loop/1&lt;/code&gt; function is quite stupid. It will simply read the content of the opened file until it reaches the end of it. When done, it simply return &lt;code&gt;:ok&lt;/code&gt;. In fact, this step is very important, because it will load all the macros from the file and store them in the &lt;code&gt;epp&lt;/code&gt; server's state.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;  &lt;span class="k"&gt;defp&lt;/span&gt; &lt;span class="n"&gt;definitions_loop&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pid&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;msg&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="ss"&gt;:epp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;parse_erl_form&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pid&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="n"&gt;msg&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:eof&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
        &lt;span class="ss"&gt;:ok&lt;/span&gt;
      &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
        &lt;span class="n"&gt;definitions_loop&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pid&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;definitions_macros/1&lt;/code&gt; function sends the undocumented &lt;code&gt;:macro_defs&lt;/code&gt; message to the &lt;code&gt;eep&lt;/code&gt; server and wait for its answer containing the list of all parsed macros from the source code. Those macros (a list of tuple) is then returned.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;  &lt;span class="k"&gt;defp&lt;/span&gt; &lt;span class="n"&gt;definitions_macros&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pid&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pid&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:epp_request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="ss"&gt;:macro_defs&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="k"&gt;receive&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:epp_reply&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;pid&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;macros&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
        &lt;span class="ss"&gt;:epp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;close&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pid&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:ok&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;macros&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="n"&gt;msg&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
        &lt;span class="ss"&gt;:epp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;close&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pid&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:error&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="k"&gt;after&lt;/span&gt;
        &lt;span class="mi"&gt;10000&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
          &lt;span class="ss"&gt;:epp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;close&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pid&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
          &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:error&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:timeout&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Every raw macros from the &lt;a href="https://www.erlang.org/doc/apps/stdlib/epp.html" rel="noopener noreferrer"&gt;&lt;code&gt;epp&lt;/code&gt;&lt;/a&gt; server's state must be converted. The &lt;code&gt;convert_macros/2&lt;/code&gt; and &lt;code&gt;convert_macros_value/1&lt;/code&gt; functions are doing the conversion and the filtering. Indeed, we are looking only for the static macros right now, not for the one with an arity, then, only the macros set to &lt;code&gt;:none&lt;/code&gt; are kept, the rest are simply dropped.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;  &lt;span class="k"&gt;defp&lt;/span&gt; &lt;span class="n"&gt;convert_macros&lt;/span&gt;&lt;span class="p"&gt;([],&lt;/span&gt; &lt;span class="n"&gt;buffer&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:ok&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="n"&gt;buffer&lt;/span&gt;
      &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Enum&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="ss"&gt;:ignored&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
          &lt;span class="no"&gt;false&lt;/span&gt;
        &lt;span class="k"&gt;else&lt;/span&gt;
          &lt;span class="no"&gt;true&lt;/span&gt;
        &lt;span class="k"&gt;end&lt;/span&gt;
     &lt;span class="k"&gt;end&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;defp&lt;/span&gt; &lt;span class="n"&gt;convert_macros&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="n"&gt;macro&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{{&lt;/span&gt;&lt;span class="ss"&gt;:atom&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;rest&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;buffer&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;with&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:ok&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;term&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="n"&gt;convert_macro_value&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
      &lt;span class="n"&gt;convert_macros&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rest&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[{&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;term&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;buffer&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
    &lt;span class="k"&gt;else&lt;/span&gt;
      &lt;span class="n"&gt;error&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:error&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;error&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;macro&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;defp&lt;/span&gt; &lt;span class="n"&gt;convert_macro_value&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="ss"&gt;none:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:none&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;}])&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;with&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:ok&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;term&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="ss"&gt;:erl_parse&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;parse_term&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="o"&gt;++&lt;/span&gt; &lt;span class="p"&gt;[{&lt;/span&gt;&lt;span class="ss"&gt;:dot&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1131&lt;/span&gt;&lt;span class="p"&gt;}])&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:ok&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;term&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;defp&lt;/span&gt; &lt;span class="n"&gt;convert_macro_value&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:ok&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:ignored&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;escape_keys/2&lt;/code&gt; function will escape the Erlang macros definitions to insert them safely in the module template via the &lt;a href="https://elixir.hexdocs.pm/main/Macro.html#escape/2" rel="noopener noreferrer"&gt;&lt;code&gt;Macro.escape/2&lt;/code&gt;&lt;/a&gt; function.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;  &lt;span class="k"&gt;defp&lt;/span&gt; &lt;span class="n"&gt;escape_keys&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;module&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;filepath&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;with&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:ok&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;defs&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="n"&gt;definitions&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;module&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;filepath&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
      &lt;span class="n"&gt;defs&lt;/span&gt;
      &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="ss"&gt;:maps&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;from_list&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
      &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Macro&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;escape&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;macro_keys/2&lt;/code&gt; and &lt;code&gt;macro_values/2&lt;/code&gt; functions are respectively extracting the keys and the values of the macros, converting them into a &lt;code&gt;[term()]&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;  &lt;span class="k"&gt;defp&lt;/span&gt; &lt;span class="n"&gt;macro_keys&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;module&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;filepath&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;with&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:ok&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;defs&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="n"&gt;definitions&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;module&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;filepath&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
      &lt;span class="n"&gt;defs&lt;/span&gt;
      &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Enum&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="n"&gt;k&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;k&lt;/span&gt; &lt;span class="k"&gt;end&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Macro&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;escape&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;defp&lt;/span&gt; &lt;span class="n"&gt;macro_values&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;module&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;filepath&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;with&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:ok&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;defs&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="n"&gt;definitions&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;module&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;filepath&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
      &lt;span class="n"&gt;defs&lt;/span&gt;
      &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Enum&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;v&lt;/span&gt; &lt;span class="k"&gt;end&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Macro&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;escape&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The module template definition is probably the most important part here, because it will integrate the data from the Erlang macros into the Elixir AST. 5 functions have been created to help users to check their macros:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;macros/0&lt;/code&gt;: returns the macros as a &lt;code&gt;Map.t()&lt;/code&gt;;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;macro/1&lt;/code&gt;: returns the value of a defined macros using its &lt;code&gt;key&lt;/code&gt;;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;macro_keys/0&lt;/code&gt;: returns the list of all macro's keys;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;macro_values/0&lt;/code&gt;: returns the list of all macro's values;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;macro_filter/1&lt;/code&gt;: a wrapper around &lt;code&gt;Map.filter/2&lt;/code&gt; to filter the macros.&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;  &lt;span class="k"&gt;defmacro&lt;/span&gt; &lt;span class="n"&gt;__using__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;opts&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;module&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Keyword&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;opts&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:module&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;filepath&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Keyword&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;opts&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:filepath&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;def_keys&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;escape_keys&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;module&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;filepath&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="kn"&gt;quote&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
      &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="no"&gt;Preprocessing&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Macros&lt;/span&gt;

      &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;macros&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kn"&gt;unquote&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;def_keys&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

      &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;macro&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;Map&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kn"&gt;unquote&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;def_keys&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

      &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;macro_keys&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kn"&gt;unquote&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;macro_keys&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;module&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;filepath&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

      &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;macro_values&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kn"&gt;unquote&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;macro_values&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;module&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;filepath&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

      &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;macros_filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fun&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
        &lt;span class="kn"&gt;unquote&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;def_keys&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Map&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fun&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="k"&gt;end&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Great, the goal now is to create or update a module with this template. The best target here could be the &lt;code&gt;Preprocessing.PublicKey&lt;/code&gt; module. The module to parse the Erlang macros is &lt;code&gt;:public_key&lt;/code&gt; and the path for the header is &lt;code&gt;inclyde/public_key.hrl&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="k"&gt;defmodule&lt;/span&gt; &lt;span class="no"&gt;Preprocessing&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;PublicKey&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="no"&gt;Preprocessing&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Macros&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="ss"&gt;module:&lt;/span&gt; &lt;span class="ss"&gt;:public_key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="ss"&gt;filepath:&lt;/span&gt; &lt;span class="s2"&gt;"include/public_key.hrl"&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Finally, this interface can be tested. The &lt;code&gt;definitions/2&lt;/code&gt; function returns the correct values from different header files.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;iex&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;alias &lt;/span&gt;Preprocessing.Macros
&lt;span class="go"&gt;Preprocessing.Macros

&lt;/span&gt;&lt;span class="gp"&gt;iex&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;Macros.definitions&lt;span class="o"&gt;(&lt;/span&gt;:kernel, &lt;span class="s2"&gt;"include/file.hrl"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="go"&gt;{:ok, [FILE_HRL_: 1]}

&lt;/span&gt;&lt;span class="gp"&gt;iex&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;Macros.definitions&lt;span class="o"&gt;(&lt;/span&gt;:kernel, &lt;span class="s2"&gt;"include/inet.hrl"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="go"&gt;{:ok, []}
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let have a look on the &lt;code&gt;Preprocessing.PublicKey&lt;/code&gt; module now.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;iex&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;alias &lt;/span&gt;Preprocessing.PublicKey
&lt;span class="go"&gt;alias Preprocessing.PublicKey
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;PublicKey.macros/0&lt;/code&gt; function returns all the available macros parsed from the Erlang source code as a &lt;a href="https://elixir.hexdocs.pm/Map.html" rel="noopener noreferrer"&gt;&lt;code&gt;Map.t()&lt;/code&gt;&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;iex&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;PublicKey.macros&lt;span class="o"&gt;()&lt;/span&gt;
&lt;span class="go"&gt;%{
  sect163r1: {1, 3, 132, 0, 2},
  "ub-postal-code-length": 16,
  secp256k1: {1, 3, 132, 0, 10},
  "id-RSAES-OAEP": {1, 2, 840, 113549, 1, 1, 7},
  "id-ce-policyMappings": {2, 5, 29, 33},
  "id-at-pseudonym": {2, 5, 4, 65},
  affiliationChanged: 3,
  "id-at-localityName": {2, 5, 4, 7},
  "id-at-givenName": {2, 5, 4, 42},
  "id-pkix-ocsp-service-locator": {1, 3, 6, 1, 5, 5, 7, 48, 1, 7},
  "ub-name": 32768,
  "id-qt-cps": {1, 3, 6, 1, 5, 5, 7, 2, 1},
  "pbeWithSHA1AndDES-CBC": {1, 2, 840, 113549, 1, 5, 10},
  secp160k1: {1, 3, 132, 0, 9},
  sect409k1: {1, 3, 132, 0, 36},
  "id-ce-extKeyUsage": {2, 5, 29, 37},
  "id-ml-dsa-87": {2, 16, 840, 1, 101, 3, 4, 3, 19},
  emptyString: "",
&lt;/span&gt;&lt;span class="c"&gt;  ...
&lt;/span&gt;&lt;span class="go"&gt;}
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;PublicKey.macro/1&lt;/code&gt; function is doing its job by returning the value of an existing key, or &lt;code&gt;nil&lt;/code&gt; if the key is not present.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;iex&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;PublicKey.macro&lt;span class="o"&gt;(&lt;/span&gt;:sect163r1&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="go"&gt;{1, 3, 132, 0, 2}

&lt;/span&gt;&lt;span class="gp"&gt;iex&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;PublicKey.macro&lt;span class="o"&gt;(&lt;/span&gt;:undefined&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="go"&gt;nil
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;PublicKey.macro_keys/0&lt;/code&gt; and &lt;code&gt;PublicKey.macro_values/0&lt;/code&gt; are returning respectively the keys and the values from the parsed macros.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="n"&gt;iex&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;PublicKey&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;macro_keys&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:sect163r1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:"ub-postal-code-length"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:secp256k1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:"id-RSAES-OAEP"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="ss"&gt;:"id-ce-policyMappings"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:"id-at-pseudonym"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:affiliationChanged&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="n"&gt;iex&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;PublicKey&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;macro_values&lt;/span&gt;
&lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;132&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="mi"&gt;16&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;132&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;840&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;113549&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="o"&gt;...&lt;/span&gt;
&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;At last, the &lt;code&gt;PublicKey.macro_filter/1&lt;/code&gt; can filter the keys/values from the macros to return only the one requested via the &lt;a href="https://elixir.hexdocs.pm/Map.html#filter/2" rel="noopener noreferrer"&gt;&lt;code&gt;Map.filter/2&lt;/code&gt;&lt;/a&gt; function. The following snippet is filtering the keys using a &lt;a href="https://elixir.hexdocs.pm/Regex.html" rel="noopener noreferrer"&gt;&lt;code&gt;Regex&lt;/code&gt;&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;iex&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;PublicKey.macro_filter&lt;span class="o"&gt;(&lt;/span&gt;fn &lt;span class="o"&gt;({&lt;/span&gt;key,_value&lt;span class="o"&gt;})&lt;/span&gt; -&amp;gt; 
&lt;span class="go"&gt;  cond do
&lt;/span&gt;&lt;span class="gp"&gt;    Regex.match?(~r"^rsa"i, Atom.to_string(key)) -&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; 
&lt;span class="gp"&gt;    true -&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;false&lt;/span&gt; 
&lt;span class="go"&gt;  end 
end)
%{
  "rSASSA-PSS-Default-Identifier": {:"RSASSA-AlgorithmIdentifier",
   {1, 2, 840, 113549, 1, 1, 10},
   {:"RSASSA-PSS-params", {:HashAlgorithm, {1, 3, 14, 3, 2, 26}, :NULL},
    {:MaskGenAlgorithm, {1, 2, 840, 113549, 1, 1, 8},
     {:HashAlgorithm, {1, 3, 14, 3, 2, 26}, :NULL}}, 20, 1}},
  "rSAES-OAEP-Default-Identifier": {:"RSAES-AlgorithmIdentifier",
   {1, 2, 840, 113549, 1, 1, 7},
   {:"RSAES-OAEP-params", {:Externalvaluereference, 354, :"PKCS-1", :sha1},
    {:Externalvaluereference, 355, :"PKCS-1", :mgf1SHA1},
    {:Externalvaluereference, 356, :"PKCS-1", :pSpecifiedEmpty}}},
  rsaEncryption: {1, 2, 840, 113549, 1, 1, 1}
}
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It is now possible to extract and convert macros from Erlang world to the Elixir universe. This implementation is perhaps not the best one, but it will make my life easier while dealing with the &lt;code&gt;public_key&lt;/code&gt; module.&lt;/p&gt;

&lt;h1&gt;
  
  
  Real World Application
&lt;/h1&gt;

&lt;p&gt;This whole post is the consequence of a sandbox project called &lt;a href="https://github.com/niamtokik/expki" rel="noopener noreferrer"&gt;&lt;code&gt;expki&lt;/code&gt;&lt;/a&gt;, created to remove all my rust from years of doing Erlang and infrastructure stuff instead of Elixir. The goal was to use Elixir and Phoenix framework to manage a small local PKI (Public Key Infrastructure) compatible with &lt;a href="https://man.openbsd.org/openssl" rel="noopener noreferrer"&gt;&lt;code&gt;openssl&lt;/code&gt;&lt;/a&gt; and &lt;a href="https://github.com/OpenVPN/easy-rsa" rel="noopener noreferrer"&gt;&lt;code&gt;easy_rsa&lt;/code&gt;&lt;/a&gt;, a tool provided by OpenVPN to manage certificates locally. In fact, when this project started, it was expected to have a working PoC quick because Erlang was already offering a good support for TLS with the &lt;a href="//www.erlang.org/doc/apps/public_key/public_key.html"&gt;&lt;code&gt;public_key&lt;/code&gt;&lt;/a&gt;, &lt;a href="https://www.erlang.org/doc/apps/crypto/crypto.html" rel="noopener noreferrer"&gt;&lt;code&gt;crypto&lt;/code&gt;&lt;/a&gt; and &lt;a href="https://www.erlang.org/doc/apps/asn1/api-reference.html" rel="noopener noreferrer"&gt;&lt;code&gt;asn1&lt;/code&gt;&lt;/a&gt; Erlang applications.&lt;/p&gt;

&lt;p&gt;Unfortunately, most of the records name present in those modules are starting with an uppercase letter... and it blocks to create something in a short amount of time. A big part of my time on &lt;code&gt;expki&lt;/code&gt; was dedicated to read the source code and the documentation of these modules or trying to find a better way to deal with the structure from them. Here the whole list of them extract from an older version of Erlang/OTP.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;from &lt;code&gt;public_key&lt;/code&gt; (157):&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;#'AAControls'{}&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;#'ACClearAttrs'{}&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;&lt;code&gt;#'AccessDescription'{}&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;#'AlgorithmIdentifier'{}&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;#'AlgorithmIdentifierPKCS5v2{}&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;#'AlgorithmIdentifierPKCS{}&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;#'AlgorithmIdentifier{}&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;#'AnotherName'{}&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;#'AttCertValidityPeriod'{}&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;#'Attribute'{}&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;#'AttributeCertificate'{}&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;#'AttributeCertificateInfo'{}&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;#'AttributePKCS{}&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;#'AttributeTypeAndValue'{}&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;#'Attributes_SETOF'{}&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;#'Attributes_SETOF_valuesWithContext_SETOF'{}&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;#'AuthorityKeyIdentifier'{}&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;#'BasicConstraints'{}&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;#'BasicOCSPResponse'{}&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;#'BuiltInDomainDefinedAttribute'{}&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;#'BuiltInStandardAttributes'{}&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;#'CertID'{}&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;#'Certificate'{}&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;#'CertificateList'{}&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;#'CertificationRequest'{}&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;#'CertificationRequestInfo'{}&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;#'CertificationRequestInfo_attributes_SETOF'{}&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;#'CertificationRequestInfo_subjectPKInfo'{}&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;#'CertificationRequestInfo_subjectPKInfo_algorithm'{}&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;#'CertificationRequest_signatureAlgorithm'{}&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;#'Characteristic{}&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;#'Clearance'{}&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;#'ContentEncryptionAlgorithmIdentifier'{}&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;#'ContentInfo'{}&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;#'Context'{}&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;#'CrlID'{}&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;#'Curve'{}&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;#'DHParameter'{}&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;#'DSAPrivateKey'{}&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;#'DigestAlgorithm'{}&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;#'DigestAlgorithmIdentifier'{}&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;#'DigestEncryptionAlgorithmIdentifier'{}&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;#'DigestInfoPKCS{}&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;#'DigestedData'{}&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;#'DistributionPoint'{}&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;#'DomainParameters'{}&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;#'Dss{}&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;#'ECDSA{}&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;#'ECParameters'{}&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;#'ECPoint'{}&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;#'ECPrivateKey'{}&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;#'EDIPartyName'{}&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;#'EncryptedContentInfo'{}&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;#'EncryptedData'{}&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;#'EncryptedPrivateKeyInfo'{}&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;#'EncryptedPrivateKeyInfo_encryptionAlgorithm'{}&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;#'EnvelopedData'{}&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;#'ExtendedNetworkAddress_e163{}&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;#'Extension'{}&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;#'ExtensionAttribute'{}&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;#'Extension{}&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;#'FieldID'{}&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;#'GeneralSubtree'{}&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;#'HashAlgorithm'{}&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;#'Holder'{}&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;#'IetfAttrSyntax'{}&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;#'IssuerAndSerialNumber'{}&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;#'IssuerSerial'{}&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;#'IssuingDistributionPoint'{}&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;#'KeyEncryptionAlgorithmIdentifier'{}&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;#'MaskGenAlgorithm'{}&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;#'NameConstraints'{}&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;#'NoticeReference'{}&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;#'OCSPRequest'{}&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;#'OCSPResponse'{}&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;#'ORAddress'{}&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;#'OTPAttributeTypeAndValue'{}&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;#'OTPCertificate'{}&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;#'OTPCharacteristic{}&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;#'OTPExtension'{}&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;#'OTPExtensionAttribute'{}&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;#'OTPFieldID'{}&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;#'OTPNoticeReference'{}&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;#'OTPOLDSubjectPublicKeyInfo'{}&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;#'OTPOLDSubjectPublicKeyInfo_algorithm'{}&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;#'OTPSubjectPublicKeyInfo'{}&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;#'OTPSubjectPublicKeyInfo{}&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;#'OTPTBSCertificate'{}&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;#'OTPUserNotice'{}&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;#'ObjectDigestInfo'{}&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;#'OneAsymmetricKey'{}&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;#'OneAsymmetricKey_privateKeyAlgorithm'{}&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;#'OtherPrimeInfo'{}&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;#'PBEParameter'{}&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;#'PBES2{}&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;#'PBKDF2{}&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;#'PBMAC1{}&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;#'PDSParameter'{}&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;#'PKAttribute'{}&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;#'PKAttribute_valuesWithContext_SETOF'{}&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;#'PSourceAlgorithm'{}&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;#'Pentanomial'{}&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;#'PersonalName'{}&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;#'PolicyConstraints'{}&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;#'PolicyInformation'{}&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;#'PolicyMappings_SEQOF'{}&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;#'PolicyQualifierInfo'{}&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;#'PreferredSignatureAlgorithm'{}&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;#'PresentationAddress'{}&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;#'PrivateKeyInfo'{}&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;#'PrivateKeyInfo_privateKeyAlgorithm'{}&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;#'PrivateKeyUsagePeriod'{}&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;#'PublicKeyAlgorithm'{}&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;#'RC2{}&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;#'RC5{}&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;#'RSAES{}&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;#'RSAPrivateKey'{}&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;#'RSAPublicKey'{}&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;#'RSASSA{}&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;#'RecipientInfo'{}&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;#'Request'{}&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;#'ResponseBytes'{}&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;#'ResponseData'{}&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;#'RevokedInfo'{}&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;#'RoleSyntax'{}&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;#'SecurityCategory'{}&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;#'ServiceLocator'{}&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;#'Signature'{}&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;#'SignatureAlgorithm'{}&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;#'SignatureAlgorithm{}&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;#'SignedAndEnvelopedData'{}&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;#'SignedData'{}&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;#'SignerInfo'{}&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;#'SignerInfoAuthenticatedAttributes_aaSequence_SEQOF'{}&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;#'SignerInfoAuthenticatedAttributes_aaSet_SETOF'{}&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;#'SignerInfo_unauthenticatedAttributes_uaSequence_SEQOF'{}&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;#'SignerInfo_unauthenticatedAttributes_uaSet_SETOF'{}&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;#'SingleResponse'{}&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;#'SubjectPublicKeyInfo'{}&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;#'SubjectPublicKeyInfoAlgorithm'{}&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;#'SubjectPublicKeyInfo{}&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;#'SvceAuthInfo'{}&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;#'TBSCertList'{}&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;#'TBSCertList_revokedCertificates_SEQOF'{}&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;#'TBSCertificate'{}&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;#'TBSRequest'{}&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;#'TargetCert'{}&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;#'TeletexDomainDefinedAttribute'{}&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;#'TeletexPersonalName'{}&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;#'UnformattedPostalAddress'{}&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;#'UserNotice'{}&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;#'V2Form'{}&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;#'ValidationParms'{}&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;#'Validity'{}&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;#cert{}&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;#path_validation_state{}&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;#revoke_state{}&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;from &lt;code&gt;asn1&lt;/code&gt; (31):&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;#'ComponentType'{}&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;#'Constraint'{}&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;#'EXTENSIONMARK'{}&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;#'ExtensionAdditionGroup'{}&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;#'Externaltypereference'{}&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;#'Externalvaluereference'{}&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;#'Object'{}&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;#'ObjectClassFieldType'{}&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;#'ObjectSet'{}&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;#'SEQUENCE'{}&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;#'SET'{}&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;#'SymbolsFromModule'{}&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;#abst{}&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;#classdef{}&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;#cmap{}&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;#gen_state{}&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;#gen{}&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;#module{}&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;#objectclass{}&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;#pobjectdef{}&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;#pobjectsetdef{}&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;#ptypedef{}&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;#pvaluedef{}&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;#pvaluesetdef{}&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;#seqtag{}&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;#simpletableattributes{}&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;#state{}&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;#tag{}&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;#typedef{}&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;#type{}&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;#valuedef{}&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That's a lot, right? In reality, not all are required for a Poc, only ~10 or ~20 of them will be used. This is where the &lt;code&gt;preprocessing&lt;/code&gt; will help, by creating the right interface for the right object. This post is already way to long... And we will see that on another one.&lt;/p&gt;

&lt;h1&gt;
  
  
  A Quick Note About &lt;code&gt;epp_dodger&lt;/code&gt; Module
&lt;/h1&gt;

&lt;p&gt;&lt;a href="https://www.erlang.org/doc/apps/syntax_tools/epp_dodger.html" rel="noopener noreferrer"&gt;&lt;code&gt;epp_dodger&lt;/code&gt;&lt;/a&gt; is another module available in the Erlang OTP toolsuite to parse valid Erlang source code. So, why not using it instead of &lt;a href="https://www.erlang.org/doc/apps/stdlib/epp.html" rel="noopener noreferrer"&gt;&lt;code&gt;epp&lt;/code&gt;&lt;/a&gt; and all the complexity relative to its server?&lt;/p&gt;

&lt;p&gt;Firstly because I wanted to dig a bit more in the Erlang parsing process. Most of my researches were focused on the "default execution path", and I totally missed &lt;a href="https://www.erlang.org/doc/apps/syntax_tools/epp_dodger.html" rel="noopener noreferrer"&gt;&lt;code&gt;epp_dodger&lt;/code&gt;&lt;/a&gt;, even if I read the documentation.&lt;/p&gt;

&lt;p&gt;Secondly, the &lt;a href="https://www.erlang.org/doc/apps/syntax_tools/epp_dodger.html" rel="noopener noreferrer"&gt;&lt;code&gt;epp_dodger&lt;/code&gt;&lt;/a&gt; module was not loaded by default with &lt;code&gt;iex&lt;/code&gt; (this module is from the &lt;a href="https://www.erlang.org/docs/18/apps/syntax_tools/index.html" rel="noopener noreferrer"&gt;&lt;code&gt;syntax_tools&lt;/code&gt;&lt;/a&gt; application) and &lt;a href="https://www.erlang.org/doc/apps/stdlib/epp.html" rel="noopener noreferrer"&gt;&lt;code&gt;epp&lt;/code&gt;&lt;/a&gt; was already available (this module is from the &lt;code&gt;stdlib&lt;/code&gt; application).&lt;/p&gt;

&lt;p&gt;Thirdly, the Erlang toolbox is huge, I don't even think someone know every single tool available there. Every time I start to work on Erlang/OTP source code, I discover new utils.&lt;/p&gt;

&lt;p&gt;Finally, it was not planned to implement my own interface to the &lt;a href="https://www.erlang.org/doc/apps/public_key/public_key.html" rel="noopener noreferrer"&gt;&lt;code&gt;public_key&lt;/code&gt;&lt;/a&gt; module, I also missed the &lt;a href="https://x509.hexdocs.pm" rel="noopener noreferrer"&gt;&lt;code&gt;x509&lt;/code&gt;&lt;/a&gt; from hex. In fact, it is also interesting to see the differences between both implementation and it will also give me a way to improve the test suite.&lt;/p&gt;

&lt;p&gt;Anyway, let fix that with a quick example of &lt;a href="https://www.erlang.org/doc/apps/syntax_tools/epp_dodger.html" rel="noopener noreferrer"&gt;&lt;code&gt;epp_dodger&lt;/code&gt;&lt;/a&gt; usage. If you want to have it in Elixir, you will need to load the &lt;a href="https://www.erlang.org/docs/18/apps/syntax_tools/index.html" rel="noopener noreferrer"&gt;&lt;code&gt;syntax_tools&lt;/code&gt;&lt;/a&gt; application.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;Application.ensure_all_started&lt;span class="o"&gt;(&lt;/span&gt;:syntax_tools&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="go"&gt;{:ok, [:syntax_tools]}
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then, the function &lt;a href="https://www.erlang.org/doc/apps/syntax_tools/epp_dodger.html#parse_file/1" rel="noopener noreferrer"&gt;&lt;code&gt;:epp_dodger.parse_file/1&lt;/code&gt;&lt;/a&gt; can be called&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;:code.lib_dir&lt;span class="o"&gt;(&lt;/span&gt;:public_key&lt;span class="o"&gt;)&lt;/span&gt;, &lt;span class="s2"&gt;"include/public_key.hrl"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
&lt;span class="gp"&gt;  |&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;Path.join&lt;span class="o"&gt;()&lt;/span&gt;
&lt;span class="gp"&gt;  |&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;:epp_dodger.parse_file&lt;span class="o"&gt;()&lt;/span&gt;
&lt;span class="go"&gt;{:ok,
 [
   {:tree, :attribute, {:attr, 24, [], :none},
    {:attribute, {:atom, 24, :ifndef}, [{:atom, 24, :public_key}]}},
   {:tree, :attribute, {:attr, 25, [], :none},
    {:attribute, {:atom, 25, :define},
     [{:atom, 25, :public_key}, {:atom, 25, true}]}},
   {:tree, :attribute, {:attr, 31, [], :none},
    {:attribute, {:atom, 31, :define},
     [
       {:atom, 31, :"pkcs-1"},
       {:tree, :tuple, {:attr, 31, [], :none},
        [
          {:integer, 31, 1},
          {:integer, 31, 2},
          {:integer, 31, 840},
          {:integer, 31, 113549},
          {:integer, 31, 1},
          {:integer, 31, 1}
        ]}
     ]}},
   {:tree, :attribute, {...}, ...},
&lt;/span&gt;&lt;span class="c"&gt;   ...
&lt;/span&gt;&lt;span class="go"&gt; ]}
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now is the better way? I would think using &lt;a href="https://www.erlang.org/doc/apps/syntax_tools/epp_dodger.html" rel="noopener noreferrer"&gt;&lt;code&gt;epp_dodger&lt;/code&gt;&lt;/a&gt; can be a better solution, the &lt;a href="https://www.erlang.org/doc/apps/syntax_tools/epp_dodger.html#parse_file/1" rel="noopener noreferrer"&gt;&lt;code&gt;:epp_dodger.parse_file/1&lt;/code&gt;&lt;/a&gt; function is documented, this is not the case when it comes to the &lt;a href="https://www.erlang.org/doc/apps/stdlib/epp.html" rel="noopener noreferrer"&gt;&lt;code&gt;epp&lt;/code&gt;&lt;/a&gt; server solution. I also assume the &lt;code&gt;epp_dodger&lt;/code&gt; module, because documented, will be more stable in the future than &lt;a href="https://www.erlang.org/doc/apps/stdlib/epp.html" rel="noopener noreferrer"&gt;&lt;code&gt;epp&lt;/code&gt;&lt;/a&gt;. In the end, for this first test release, I think it should do the job.&lt;/p&gt;

&lt;h1&gt;
  
  
  Conclusion
&lt;/h1&gt;

&lt;p&gt;Even if the interoperability is great between Erlang and Elixir, some part has been ignored or simply discarded because only few people will be interested to use those features. Dealing with Erlang Preprocessor is one of them I guess. In fine, when one knows how Erlang is working, and where to investigate, it becomes an easy problem to fix. Yeah, it can take few hours to understand how the bricks are working, but in the end, it's not lost. Learning how the BEAM is working, and how Erlang is parsed is a fundamental knowledge anyone should have when using this ecosystem.&lt;/p&gt;

&lt;p&gt;Long time ago, I worked on an implementation of &lt;a href="https://github.com/niamtokik/zfs" rel="noopener noreferrer"&gt;ZFS&lt;/a&gt; (ZettaFileSystem) in Erlang, even if it was working for many things, it was slow and limited to a small amount of the features exposed by ZFS. One of my problem was to deal with all the internal C structure defined in ZFS, evolving sometimes between versions... but also doing mistake by implementing them poorly on the Erlang side as binaries or functions. Having a feature like this one here would have been a game changer, converting a data-structure in C into an Erlang or Elixir function would have be just crazy!&lt;/p&gt;

&lt;p&gt;Anyway, as usual, a long list of links if you are interested to know more on this topic:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://erlang.github.io/prs/9333/doc/system/code_loading.html" rel="noopener noreferrer"&gt;Erlang Code Loading&lt;/a&gt; from the official Erlang documentation, where you will learn how Erlang code is loaded;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://www.erlang.org/doc/apps/erts/absform.html" rel="noopener noreferrer"&gt;Erlang Abstract Format&lt;/a&gt; from the official Erlang documentation, where you will learn what the Erlang abstract form is made of;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://www.erlang.org/doc/apps/erts/erlc_cmd.html" rel="noopener noreferrer"&gt;&lt;code&gt;erlc&lt;/code&gt; command documentation&lt;/a&gt; and &lt;a href="https://github.com/erlang/otp/blob/master/lib/stdlib/src/erl_compile.erl" rel="noopener noreferrer"&gt;its source code&lt;/a&gt; from the official Erlang documentation where you will learn how to use the &lt;code&gt;erlc&lt;/code&gt; command;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://www.erlang.org/doc/apps/compiler/cerl.html" rel="noopener noreferrer"&gt;Core Erlang abstract syntax trees&lt;/a&gt; from the official Erlang documentation, where you will learn about the Erlang abstract syntact tree and how to generate ot;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://www.erlang.org/doc/apps/compiler/compile.html" rel="noopener noreferrer"&gt;The Erlang compiler&lt;/a&gt; and its &lt;a href="https://github.com/erlang/otp/blob/master/lib/compiler/src/compile.erl" rel="noopener noreferrer"&gt;source code&lt;/a&gt; from the official Erlang documentation, where you will learn how the Erlang compiler works;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://www.erlang.org/doc/apps/stdlib/epp.html" rel="noopener noreferrer"&gt;&lt;code&gt;epp&lt;/code&gt; (erlang preprocessor) documentation&lt;/a&gt; and its &lt;a href="https://github.com/erlang/otp/blob/master/lib/stdlib/src/epp.erl" rel="noopener noreferrer"&gt;source code&lt;/a&gt; from the official Erlang documentation where you will learn and understand the Erlang preprocessor;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://www.erlang.org/doc/apps/stdlib/erl_anno.html" rel="noopener noreferrer"&gt;&lt;code&gt;erl_anno&lt;/code&gt; (compiler annotation) documentation&lt;/a&gt; and its &lt;a href="https://github.com/erlang/otp/blob/master/lib/stdlib/src/erl_anno.erl" rel="noopener noreferrer"&gt;source code&lt;/a&gt; from the official Erlang documentation, where you will learn about the Erlang compiler annotations;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://www.erlang.org/doc/apps/stdlib/erl_scan.html" rel="noopener noreferrer"&gt;&lt;code&gt;erl_scan&lt;/code&gt; (scanner) documentation&lt;/a&gt; and its &lt;a href="https://github.com/erlang/otp/blob/master/lib/stdlib/src/erl_scan.erl" rel="noopener noreferrer"&gt;source code&lt;/a&gt; from the official Erlang documentation, where the tokens are produced direct after reading the source code;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://www.erlang.org/doc/apps/stdlib/erl_parse.html" rel="noopener noreferrer"&gt;&lt;code&gt;erl_parse&lt;/code&gt; (parser) documentation&lt;/a&gt; and its &lt;a href="https://github.com/erlang/otp/blob/master/lib/stdlib/src/erl_parse.yrl" rel="noopener noreferrer"&gt;source code&lt;/a&gt; from the official Erlang documentation, where the AST is generated from the tokens previously created by the scanner;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://www.erlang.org/doc/apps/stdlib/io.html" rel="noopener noreferrer"&gt;&lt;code&gt;io&lt;/code&gt; module documentation&lt;/a&gt; and its &lt;a href="https://github.com/erlang/otp/blob/master/lib/stdlib/src/io.erl" rel="noopener noreferrer"&gt;source code&lt;/a&gt; from the official Erlang documentation, where you can find more information about the I/O protocols;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://www.erlang.org/doc/apps/stdlib/io_lib.html" rel="noopener noreferrer"&gt;&lt;code&gt;io_lib&lt;/code&gt; module documentation&lt;/a&gt; and its &lt;a href="https://github.com/erlang/otp/blob/master/lib/stdlib/src/io_lib.erl" rel="noopener noreferrer"&gt;source code&lt;/a&gt; from the official Erlang documentation;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://github.com/zuiderkwast/erlang_abstract_format" rel="noopener noreferrer"&gt;&lt;code&gt;Erlang Abstract Format&lt;/code&gt;&lt;/a&gt; on Github, where you will have another view of the Erlang Abstract Format;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://github.com/happi/theBeamBook" rel="noopener noreferrer"&gt;The Beam Book&lt;/a&gt; on Github, where you find a lot of interesting information about the low-level datastructures and how the BEAM is working.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://github.com/niamtokik/expki" rel="noopener noreferrer"&gt;&lt;code&gt;expki&lt;/code&gt; source code&lt;/a&gt; on Github, where the Erlang record and macro issues were found, while developing a PKI manager;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://github.com/niamtokik/preprocessing" rel="noopener noreferrer"&gt;&lt;code&gt;preprocessing&lt;/code&gt; source code&lt;/a&gt; on Github, created while writing this article, and to use it as library on other projects.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Have fun and happy hacking!&lt;/p&gt;




&lt;p&gt;Cover Image by &lt;a href="https://unsplash.com/@igrindphoto?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" rel="noopener noreferrer"&gt;Evgeniy Smersh&lt;/a&gt; on &lt;a href="https://unsplash.com/photos/a-shelf-filled-with-lots-of-bottles-of-liquid-aWnA944oXLE?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" rel="noopener noreferrer"&gt;Unsplash&lt;/a&gt;&lt;/p&gt;

</description>
      <category>erlang</category>
      <category>elixir</category>
      <category>programming</category>
      <category>interface</category>
    </item>
    <item>
      <title>Q&amp;D: ExUnit and Blob Fixture in Elixir</title>
      <dc:creator>Mathieu Kerjouan</dc:creator>
      <pubDate>Wed, 30 Sep 2026 10:00:00 +0000</pubDate>
      <link>https://dev.to/niamtokik/qd-exunit-and-blob-fixture-in-elixir-ej0</link>
      <guid>https://dev.to/niamtokik/qd-exunit-and-blob-fixture-in-elixir-ej0</guid>
      <description>&lt;p&gt;Another quick and dirty post regarding Elixir. This one will be really quick, but I was working on test unit recently, and was stuck for few minutes about where I could put my fixtures, and especially... some raw blobs. In Erlang, with &lt;code&gt;common_test&lt;/code&gt;, the path is directly passed in the options and it is easy to use. In Elixir, it's a bit different, the relative path of the test suite is stored in the &lt;a href="https://elixir.hexdocs.pm/1.12/Kernel.SpecialForms.html#__DIR__/0" rel="noopener noreferrer"&gt;&lt;code&gt;__DIR__&lt;/code&gt;&lt;/a&gt; macro. This small trick get lost in my mind. Here an example.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;mix new blob
&lt;span class="go"&gt;* creating README.md
* creating .formatter.exs
* creating .gitignore
* creating mix.exs
* creating lib
* creating lib/blob.ex
* creating test
* creating test/test_helper.exs
* creating test/blob_test.exs

Your Mix project was created successfully.
You can use "mix" to compile it, test it, and more:

    cd blob
    mix test

Run "mix help" for more commands.

&lt;/span&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;cd &lt;/span&gt;blob
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A fixtures directory can be helpful, let creates one.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;mkdir&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; &lt;span class="nb"&gt;test&lt;/span&gt;/fixtures
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To do the test, let create also a file called &lt;code&gt;blob.txt&lt;/code&gt; containing an encoded string in base64 via &lt;a href="https://man.openbsd.org/openssl#enc" rel="noopener noreferrer"&gt;&lt;code&gt;openssl&lt;/code&gt;&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;printf&lt;/span&gt; &lt;span class="s2"&gt;"this is a test"&lt;/span&gt; | openssl enc &lt;span class="nt"&gt;-base64&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;test&lt;/span&gt;/fixture/blob.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The project created for this example is a simple library, the project configuration file &lt;a href="https://elixir.hexdocs.pm/introduction-to-mix.html#project-compilation" rel="noopener noreferrer"&gt;&lt;code&gt;mix.exs&lt;/code&gt;&lt;/a&gt; must be updated to allow other files to be loaded during the test execution. This is configured in &lt;a href="https://mix.hexdocs.pm/Mix.Tasks.Test.html#module-configuration" rel="noopener noreferrer"&gt;&lt;code&gt;:test_load_filters&lt;/code&gt;&lt;/a&gt; section, all files ending with &lt;code&gt;_test.exs&lt;/code&gt; and &lt;code&gt;_fixtures.exs&lt;/code&gt; must be loaded.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="k"&gt;defmodule&lt;/span&gt; &lt;span class="no"&gt;Blob&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;MixProject&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="no"&gt;Mix&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Project&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;project&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="p"&gt;[&lt;/span&gt;
      &lt;span class="ss"&gt;app:&lt;/span&gt; &lt;span class="ss"&gt;:blob&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="ss"&gt;version:&lt;/span&gt; &lt;span class="s2"&gt;"0.1.0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="ss"&gt;elixir:&lt;/span&gt; &lt;span class="s2"&gt;"~&amp;gt; 1.19"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="ss"&gt;start_permanent:&lt;/span&gt; &lt;span class="no"&gt;Mix&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;env&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="ss"&gt;:prod&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="ss"&gt;deps:&lt;/span&gt; &lt;span class="n"&gt;deps&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
      &lt;span class="ss"&gt;test_load_filters:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="no"&gt;String&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ends_with?&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;&amp;amp;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"_test.exs"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="no"&gt;String&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ends_with?&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;&amp;amp;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"_fixtures.exs"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="c1"&gt;# ...&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;An helper function to have access to the fixtures can be created. It's not mandatory, but it's easier to call something like &lt;code&gt;BlobFixtures.read_blob/1&lt;/code&gt; instead of recreating the same procedure everytime. DRY.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="k"&gt;defmodule&lt;/span&gt; &lt;span class="no"&gt;BlobFixtures&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;read_blob&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;relative_path&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;__DIR__&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"fixtures"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;relative_path&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Path&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;join&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;File&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;read!&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The test suite can now be updated. The blob is read from the file system and pushed in the test suite.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="k"&gt;defmodule&lt;/span&gt; &lt;span class="no"&gt;BlobTest&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="no"&gt;ExUnit&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Case&lt;/span&gt;
  &lt;span class="n"&gt;doctest&lt;/span&gt; &lt;span class="no"&gt;Blob&lt;/span&gt;

  &lt;span class="c1"&gt;# ...&lt;/span&gt;

  &lt;span class="n"&gt;test&lt;/span&gt; &lt;span class="s2"&gt;"read from file"&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;assert&lt;/span&gt; &lt;span class="s2"&gt;"this is a test"&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt;
      &lt;span class="no"&gt;BlobFixtures&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;read_blob&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"blob.txt"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;String&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;trim&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
      &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Base&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;decode64!&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
      &lt;span class="c1"&gt;# only for the example&lt;/span&gt;
      &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;IO&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;inspect&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Finally, &lt;a href="https://mix.hexdocs.pm/Mix.Tasks.Test.html" rel="noopener noreferrer"&gt;&lt;code&gt;mix test&lt;/code&gt;&lt;/a&gt; can be called, and it should be green. The decoded message should be printed as well.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;mix &lt;span class="nb"&gt;test&lt;/span&gt;
&lt;span class="go"&gt;Running ExUnit with seed: 423336, max_cases: 16

"this is a test"
&lt;/span&gt;&lt;span class="c"&gt;...
&lt;/span&gt;&lt;span class="go"&gt;Finished in 0.04 seconds (0.00s async, 0.04s sync)
1 doctest, 2 tests, 0 failures
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Indeed, it was a quick note! As usual, have fun and happy hacking!&lt;/p&gt;




&lt;p&gt;Cover Image by &lt;a href="https://unsplash.com/@connorgan?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" rel="noopener noreferrer"&gt;Connor Gan&lt;/a&gt; on &lt;a href="https://unsplash.com/photos/glowing-potion-bottle-lamp-and-blocks-F7zCI2jTR2A?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" rel="noopener noreferrer"&gt;Unsplash&lt;/a&gt;&lt;/p&gt;

</description>
      <category>elixir</category>
      <category>testing</category>
      <category>programming</category>
      <category>exunit</category>
    </item>
    <item>
      <title>Q&amp;D: Anonymous Recursive Functions in Elixir</title>
      <dc:creator>Mathieu Kerjouan</dc:creator>
      <pubDate>Tue, 29 Sep 2026 10:00:00 +0000</pubDate>
      <link>https://dev.to/niamtokik/qd-anonymous-recursive-functions-in-elixir-4oop</link>
      <guid>https://dev.to/niamtokik/qd-anonymous-recursive-functions-in-elixir-4oop</guid>
      <description>&lt;p&gt;Some people prefer Elixir syntax over Erlang syntax, that's their opinion, but if you are like me, you probably knows how Erlang explicitness and conciseness make everything better. I recently needed to quickly debug a piece of code on a running node using Elixir, and while doing that, spawning processes can be helpful to store information, simulate stuff and so on. In Erlang, a recursive anonymous function looks like that:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;1&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;F &lt;span class="o"&gt;=&lt;/span&gt; fun F&lt;span class="o"&gt;()&lt;/span&gt; -&amp;gt;
&lt;span class="go"&gt;  receive
&lt;/span&gt;&lt;span class="gp"&gt;    exit -&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;ok&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="gp"&gt;    Msg -&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;io:format&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"~p~n"&lt;/span&gt;, &lt;span class="o"&gt;[&lt;/span&gt;Msg]&lt;span class="o"&gt;)&lt;/span&gt;,
&lt;span class="go"&gt;    F()
  end
end.
&lt;/span&gt;&lt;span class="gp"&gt;#&lt;/span&gt;Fun&amp;lt;erl_eval.20.113135111&amp;gt;
&lt;span class="go"&gt;
&lt;/span&gt;&lt;span class="gp"&gt;2&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;P &lt;span class="o"&gt;=&lt;/span&gt; spawn&lt;span class="o"&gt;(&lt;/span&gt;F&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="nb"&gt;.&lt;/span&gt;
&lt;span class="gp"&gt;&amp;lt;0.151.0&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="go"&gt;
&lt;/span&gt;&lt;span class="gp"&gt;3&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;P &lt;span class="o"&gt;!&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;self&lt;span class="o"&gt;()&lt;/span&gt;, &lt;span class="nb"&gt;test&lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt;&lt;span class="nb"&gt;.&lt;/span&gt;
&lt;span class="gp"&gt;{&amp;lt;0.113.0&amp;gt;&lt;/span&gt;,test&lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="gp"&gt;{&amp;lt;0.113.0&amp;gt;&lt;/span&gt;,test&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The same is a bit different in Elixir, due to the syntax. Based on the documentation, it is not fixed, but if I'm wrong, don't hesitate to comment. Anyway, here the solution:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;iex&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;f &lt;span class="o"&gt;=&lt;/span&gt; fn &lt;span class="o"&gt;(&lt;/span&gt;f&lt;span class="o"&gt;)&lt;/span&gt; -&amp;gt;
&lt;span class="go"&gt;  receive do
&lt;/span&gt;&lt;span class="gp"&gt;    :exit -&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;:ok
&lt;span class="gp"&gt;    msg -&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; 
&lt;/span&gt;&lt;span class="go"&gt;      IO.inspect(msg)
      f.(f)
  end
end
&lt;/span&gt;&lt;span class="gp"&gt;#&lt;/span&gt;Function&amp;lt;42.113135111/1 &lt;span class="k"&gt;in&lt;/span&gt; :erl_eval.expr/6&amp;gt;
&lt;span class="go"&gt;
&lt;/span&gt;&lt;span class="gp"&gt;iex&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;p &lt;span class="o"&gt;=&lt;/span&gt; spawn&lt;span class="o"&gt;(&lt;/span&gt;fn -&amp;gt; f.&lt;span class="o"&gt;(&lt;/span&gt;f&lt;span class="o"&gt;)&lt;/span&gt; end&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="gp"&gt;#&lt;/span&gt;PID&amp;lt;0.725.0&amp;gt;
&lt;span class="go"&gt;
&lt;/span&gt;&lt;span class="gp"&gt;iex&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;send&lt;span class="o"&gt;(&lt;/span&gt;p, &lt;span class="o"&gt;{&lt;/span&gt;self&lt;span class="o"&gt;()&lt;/span&gt;, :test&lt;span class="o"&gt;})&lt;/span&gt;
&lt;span class="gp"&gt;{#&lt;/span&gt;PID&amp;lt;0.724.0&amp;gt;, :test&lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="gp"&gt;{#&lt;/span&gt;PID&amp;lt;0.724.0&amp;gt;, :test&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Just to be clear, the same idea can also be done in Erlang, but with the syntactic sugar around the anonymous function, it's way easier to create recursive loop.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;1&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;F2 &lt;span class="o"&gt;=&lt;/span&gt; fun &lt;span class="o"&gt;(&lt;/span&gt;F2&lt;span class="o"&gt;)&lt;/span&gt; -&amp;gt;
&lt;span class="go"&gt;  receive
&lt;/span&gt;&lt;span class="gp"&gt;    exit -&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;ok&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="gp"&gt;    Msg -&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;io:format&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"~p~n"&lt;/span&gt;, &lt;span class="o"&gt;[&lt;/span&gt;Msg]&lt;span class="o"&gt;)&lt;/span&gt;,
&lt;span class="go"&gt;    F2(F2)
  end
end.
&lt;/span&gt;&lt;span class="gp"&gt;#&lt;/span&gt;Fun&amp;lt;erl_eval.42.113135111&amp;gt;
&lt;span class="go"&gt;
&lt;/span&gt;&lt;span class="gp"&gt;2&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;P2 &lt;span class="o"&gt;=&lt;/span&gt; spawn&lt;span class="o"&gt;(&lt;/span&gt;fun&lt;span class="o"&gt;()&lt;/span&gt; -&amp;gt; F2&lt;span class="o"&gt;(&lt;/span&gt;F2&lt;span class="o"&gt;)&lt;/span&gt; end&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="nb"&gt;.&lt;/span&gt;
&lt;span class="gp"&gt;&amp;lt;0.157.0&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="go"&gt;
&lt;/span&gt;&lt;span class="gp"&gt;3&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;P2 &lt;span class="o"&gt;!&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;self&lt;span class="o"&gt;()&lt;/span&gt;, &lt;span class="nb"&gt;test&lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt;&lt;span class="nb"&gt;.&lt;/span&gt;
&lt;span class="gp"&gt;{&amp;lt;0.113.0&amp;gt;&lt;/span&gt;,test&lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="gp"&gt;{&amp;lt;0.113.0&amp;gt;&lt;/span&gt;,test&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This method can be a bit more flexible though, because the state of the recursive function, is a function, one can create an interface to update it dynamically during code execution.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="n"&gt;iex&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;f2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;f2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
  &lt;span class="k"&gt;receive&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="ss"&gt;:exit&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="ss"&gt;:ok&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:update&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;fup&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="ow"&gt;when&lt;/span&gt; &lt;span class="n"&gt;is_function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fup&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
      &lt;span class="n"&gt;fup&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fup&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;msg&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; 
      &lt;span class="no"&gt;IO&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;inspect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="n"&gt;f2&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;f2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="c1"&gt;#Function&amp;lt;42.113135111/1 in :erl_eval.expr/6&amp;gt;&lt;/span&gt;

&lt;span class="n"&gt;iex&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;f3&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;f3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
  &lt;span class="k"&gt;receive&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="ss"&gt;:exit&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="ss"&gt;:ok&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:update&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;fup&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="ow"&gt;when&lt;/span&gt; &lt;span class="n"&gt;is_function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fup&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
      &lt;span class="n"&gt;fup&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fup&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;msg&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; 
      &lt;span class="no"&gt;IO&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;puts&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"f3: &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;inspect&lt;/span&gt; &lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="n"&gt;f3&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;f3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="c1"&gt;#Function&amp;lt;42.113135111/1 in :erl_eval.expr/6&amp;gt;&lt;/span&gt;

&lt;span class="n"&gt;iex&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;spawn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;f2&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;f2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;end&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;#PID&amp;lt;0.733.0&amp;gt;&lt;/span&gt;

&lt;span class="n"&gt;iex&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="ss"&gt;:test&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="c1"&gt;#PID&amp;lt;0.724.0&amp;gt;, :test}&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="c1"&gt;#PID&amp;lt;0.724.0&amp;gt;, :test}&lt;/span&gt;

&lt;span class="n"&gt;iex&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:update&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;f3&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:update&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;#Function&amp;lt;42.113135111/1 in :erl_eval.expr/6&amp;gt;}&lt;/span&gt;

&lt;span class="n"&gt;iex&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;  &lt;span class="n"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="ss"&gt;:test&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="c1"&gt;#PID&amp;lt;0.724.0&amp;gt;, :test}&lt;/span&gt;
&lt;span class="ss"&gt;f3:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="c1"&gt;#PID&amp;lt;0.724.0&amp;gt;, :test}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you can see, the main loop can be updated on demand, useful when we need to debug or trace something quick, and insert receive patterns.&lt;/p&gt;




&lt;p&gt;Cover Image by &lt;a href="https://unsplash.com/@rokkon?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" rel="noopener noreferrer"&gt;Jan Ranft&lt;/a&gt; on &lt;a href="https://unsplash.com/photos/clear-glass-bottles-in-brown-wooden-box-oduOp0RlPf8?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" rel="noopener noreferrer"&gt;Unsplash&lt;/a&gt;&lt;/p&gt;

</description>
      <category>elixir</category>
      <category>erlang</category>
      <category>functional</category>
      <category>programming</category>
    </item>
    <item>
      <title>WeeklyReview#202639</title>
      <dc:creator>Mathieu Kerjouan</dc:creator>
      <pubDate>Mon, 28 Sep 2026 10:00:00 +0000</pubDate>
      <link>https://dev.to/niamtokik/weeklyreview202639-438</link>
      <guid>https://dev.to/niamtokik/weeklyreview202639-438</guid>
      <description>&lt;p&gt;A lot of links this week... And I did not have the time to read them all! Enjoy!&lt;/p&gt;




&lt;p&gt;Managing scheduled posts on Linkedin changed during the past weeks. I finally got my answer from the documentation. To have access to the scheduled posts, one should start to write a new post, at the bottom of the window, a calendar icon should be present (with a number on right). Click on it and you will be able to see your scheduled post. I think Linkedin is looking for UI/UX engineers.&lt;/p&gt;




&lt;p&gt;&lt;a href="https://cranst0n.github.io/ribs/" rel="noopener noreferrer"&gt;&lt;code&gt;ribs&lt;/code&gt;&lt;/a&gt; is probably one of the most fascinating functional library available for Dart and Flutter. I started to play with it last week, but there are so many things to say about it, I don't even know how to start. &lt;a href="https://github.com/cranst0n" rel="noopener noreferrer"&gt;cranst0n&lt;/a&gt; did an amazing work, but the learning curve is crazy.&lt;/p&gt;




&lt;p&gt;One of my past interview for a Senior Elixir Backend Developer position was successful, but a technical interview including a coding test is required. My Elixir skill is rusty, my last professional usage of this language was 3 years ago, and during the past years, Erlang was my main programming language. The crust of rust is even bigger because during the past months, Dart and Flutter were my targets... Anyway, if you are reading these messages, you already know I code in Elixir (my last article on standalone http server with Bondy is a proof), but it can be hard to remove the habits from a very similar language like Erlang, even more during an interview. The backend of my main mobile application will use Elixir and Phoenix, but it is the right time... but I have an issue.&lt;/p&gt;

&lt;p&gt;Last week, my VPNs got some issues related to certificate, and the way I manage them is a bit crappy (&lt;code&gt;easy_rsa&lt;/code&gt; from openvpn toolbox). This certificate management issue is recurrent, and every 2 or 3 years, it cost me few hours to cleanup and update things. Why not storing those certificates in a postgresql database managed by Elixir? In fact, it could also be a good way to receive alerts when a CA or a client certificate expires, and automatically renew them? Well, welcome to another project called &lt;a href="https://github.com/niamtokik/expki" rel="noopener noreferrer"&gt;&lt;code&gt;expki&lt;/code&gt;&lt;/a&gt;. Again, it's not planned to be prod ready, but more to let me code like I want and relearn Elixir best practices. Perhaps you will find the source code interesting though... right?&lt;/p&gt;

&lt;p&gt;In fact, my 2 or 3 coding sessions on this project were very interesting. For example, I thought the interoperability with Erlang with smooth, but it's not the case for everything. Here a concrete use case (a post will be published about that). The &lt;a href="https://www.erlang.org/doc/apps/public_key/public_key.html" rel="noopener noreferrer"&gt;&lt;code&gt;public_key&lt;/code&gt;&lt;/a&gt; Erlang module is in charge of dealing with all the asymmetric cryptography algorithms (e.g. RSA, DSA, DSS, ECC...) and their format (PEM, DER). Because this code is fully in Erlang, it also uses a lot of &lt;code&gt;macros&lt;/code&gt; and &lt;code&gt;records&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The records can "easily" be used in Elixir with the help of the &lt;a href="https://elixir.hexdocs.pm/Record.html" rel="noopener noreferrer"&gt;&lt;code&gt;Record&lt;/code&gt;&lt;/a&gt; module, except if those records are starting with an uppercase character. Indeed, the &lt;code&gt;Record&lt;/code&gt; module will convert the records into a function, but the functions in Elixir can't use a name starting with an uppercase character. How to fix this problem then, because the &lt;a href="https://www.erlang.org/doc/apps/public_key/public_key.html" rel="noopener noreferrer"&gt;&lt;code&gt;public_key&lt;/code&gt;&lt;/a&gt; module defines more than 150 records following this pattern. Well, I did my own implementation, and instead of creating a function, it extends a module. The example below creates a &lt;a href="https://github.com/niamtokik/expki/blob/master/apps/expki/lib/expki/public_key/rsa_private_key.ex" rel="noopener noreferrer"&gt;&lt;code&gt;Expki.PublicKey.RSAPrivateKey&lt;/code&gt;&lt;/a&gt; using the &lt;a href="https://github.com/niamtokik/expki/blob/master/apps/expki/lib/expki/public_key.ex" rel="noopener noreferrer"&gt;&lt;code&gt;Expki.PublicKey&lt;/code&gt;&lt;/a&gt; module as template.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="k"&gt;defmodule&lt;/span&gt; &lt;span class="no"&gt;Expki&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;PublicKey&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;RSAPrivateKey&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;                                                                                                                                                                                                                                                                                  
  &lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="no"&gt;Expki&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;PublicKey&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;name:&lt;/span&gt; &lt;span class="ss"&gt;:RSAPrivateKey&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;pem:&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;                                                                                                                                                                                                                                                                      
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When executed, this snippet will create an Elixir &lt;code&gt;Struct&lt;/code&gt; called &lt;code&gt;%Expki.PublicKey.RSAPrivateKey{}&lt;/code&gt; containing the fields from the Erlang records and also creates few helper functions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;RSAPrivateKey.name/0&lt;/code&gt;: returns the name of the record as an &lt;code&gt;atom()&lt;/code&gt;;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;RSAPrivateKey.length/0&lt;/code&gt;: returns the full length of the record including its name;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;RSAPrivateKey.fields/0&lt;/code&gt;: returns record's fields and their default value;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;RSAPrivateKey.keys/0&lt;/code&gt;: returns record's keys;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;RSAPrivateKey.convert/1&lt;/code&gt;: convert a &lt;code&gt;%RSAPrivateKey{}&lt;/code&gt; Elixir truct into a &lt;code&gt;#RSAPrivateKey{}&lt;/code&gt; Erlang record, and vice versa;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;RSAPrivateKey.convert!/1&lt;/code&gt;: same than the previous function, but throw an error in case of issues;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;RSAPrivateKey.is_valid?/1&lt;/code&gt;: check if a record is valid or not;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;RSAPrivateKey.pem_entry_encode/1&lt;/code&gt;: extra-function added to help encoding a &lt;code&gt;%RSAPrivateKey{}&lt;/code&gt; into a PEM entry;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;RSAPrivateKey.pem_entry_decode/1&lt;/code&gt;: extra-function added to help decoding a PEM entry and convert it into a &lt;code&gt;%RSAPrivateKey{}&lt;/code&gt; struct.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Then the &lt;a href="https://www.erlang.org/doc/system/macros.html" rel="noopener noreferrer"&gt;&lt;code&gt;macros&lt;/code&gt;&lt;/a&gt;. This part is a challenging one, because the &lt;code&gt;macros&lt;/code&gt;, and especially the &lt;code&gt;-define&lt;/code&gt; annotations, are dynamically loaded when &lt;a href="https://www.erlang.org/doc/apps/stdlib/epp.html" rel="noopener noreferrer"&gt;&lt;code&gt;epp&lt;/code&gt;&lt;/a&gt; (the Erlang PreProcessor) is reading the source code. The macros are then expended, but never really returned. The only way to have a list of available macros is to call the &lt;a href="https://github.com/erlang/otp/blob/OTP-28.5/lib/stdlib/src/epp.erl#L790" rel="noopener noreferrer"&gt;&lt;code&gt;epp&lt;/code&gt; server&lt;/a&gt; started with &lt;a href="https://www.erlang.org/doc/apps/stdlib/epp.html#open/1" rel="noopener noreferrer"&gt;&lt;code&gt;epp:open/1&lt;/code&gt;&lt;/a&gt; function, and sending an undocumented message to it. Yeah, that's a bit dirty... and why do I would like to do that? Well, because, again, the &lt;a href="https://www.erlang.org/doc/apps/public_key/public_key.html" rel="noopener noreferrer"&gt;&lt;code&gt;public_key&lt;/code&gt;&lt;/a&gt; module  is using a lot of &lt;code&gt;-define&lt;/code&gt; macros to store X509-like standard informations for the certificates.&lt;/p&gt;

&lt;p&gt;All my researches and notes can be seen in the repository, in the &lt;a href="https://github.com/niamtokik/expki/tree/master/notes" rel="noopener noreferrer"&gt;notes&lt;/a&gt; directory.&lt;/p&gt;




&lt;p&gt;It was not really planned, but I also worked a bit on the &lt;a href="https://github.com/erlang-punch/awesome-erlang" rel="noopener noreferrer"&gt;Awesome Erlang List&lt;/a&gt; via Erlang Punch. Managing with so many resources is a huge issue, and it's not easy to manage a simple markdown file. 2 years ago, I started to write a solution using a text-like database, but it was just not the right way to do. Then, I started to move those resources into Erlang Terms, again, it was hard to maintain. Finally, I decided to use yaml for now. A &lt;a href="https://github.com/erlang-punch/awesome-erlang/blob/master/db.yaml" rel="noopener noreferrer"&gt;&lt;code&gt;db.yaml&lt;/code&gt;&lt;/a&gt; is now available at the root of the project, it contains the whole list of resources and will be used to generate also README.md file and few JSON files for indexing purpose.&lt;/p&gt;

&lt;p&gt;The concept behind the Awesome List is great, but it's hard to update, and not a lot of people have the time to do it. What could be nice is to provide a simple web interface (with authentication) allowing creators to put their project easily. The &lt;code&gt;awesome&lt;/code&gt; directory is containing an Erlang application/release with the goal of doing that, but it was never finished. Hopefully one day I will have more free time to do it.&lt;/p&gt;

&lt;h1&gt;
  
  
  Coding
&lt;/h1&gt;

&lt;p&gt;📝 &lt;a href="https://www.youtube.com/watch?v=4xfcVv3yn9E" rel="noopener noreferrer"&gt;&lt;strong&gt;Instant-Launch Erlang Executables - Peer Stritzinger | Code BEAM Lite Stockholm 2026&lt;/strong&gt;&lt;/a&gt;: a talk about &lt;code&gt;rebar3&lt;/code&gt; &lt;a href="https://github.com/stritzinger/rebar_calzone" rel="noopener noreferrer"&gt;&lt;code&gt;calzone&lt;/code&gt;&lt;/a&gt; module to create Erlang binaries and speeding-up the boot process. The idea is to preload the data and store them in the memory using &lt;a href="https://www.man7.org/linux/man-pages/man2/mmap.2.html" rel="noopener noreferrer"&gt;&lt;code&gt;mmap&lt;/code&gt;&lt;/a&gt;. It's an alternative to &lt;code&gt;escript&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;▶️ &lt;a href="https://www.youtube.com/watch?v=vqi-JCO_Ia8" rel="noopener noreferrer"&gt;&lt;strong&gt;Going CPU Bound - David Klemenc | Code BEAM Lite Stockholm 2026&lt;/strong&gt;&lt;/a&gt;: a quick review and history of optimizing logging in Elixir.&lt;/p&gt;

&lt;p&gt;🏗️ &lt;a href="https://github.com/0xAX/BootLife/tree/master" rel="noopener noreferrer"&gt;&lt;strong&gt;BootLife&lt;/strong&gt;&lt;/a&gt;: Conway's Game of Life running directly from a 512-byte x86 boot sector, using VGA memory as the simulation grid. By &lt;a href="https://x.com/0xAX/status/2101663120146256052?s=20" rel="noopener noreferrer"&gt;Alex Kuleshov&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;🏗️ &lt;a href="https://github.com/matheuscamarques/pon_beam" rel="noopener noreferrer"&gt;&lt;strong&gt;PON-BEAM — Notification-Oriented BEAM Virtual Machine&lt;/strong&gt;&lt;/a&gt;: PON-BEAM is a complete re-architecture of the Erlang/OTP Virtual Machine (ERTS — Erlang Run-Time System) using the Notification-Oriented Paradigm (PON).&lt;/p&gt;

&lt;p&gt;🌐 &lt;a href="https://beeceptor.com/" rel="noopener noreferrer"&gt;&lt;strong&gt;beeceptor&lt;/strong&gt;&lt;/a&gt;: a service to mock API, easy to use, fast. Perfect to implement and test http clients.&lt;/p&gt;

&lt;p&gt;🌐 &lt;a href="https://asmjit.com/asmgrid/" rel="noopener noreferrer"&gt;&lt;strong&gt;AsmGrid&lt;/strong&gt;&lt;/a&gt;: a complete list of all opcode from x86, amd64 and ARM, from &lt;a href="https://asmjit.com/" rel="noopener noreferrer"&gt;&lt;strong&gt;AsmJit&lt;/strong&gt;&lt;/a&gt;, the library used by the BEAM for its JIT.&lt;/p&gt;

&lt;p&gt;📝 &lt;a href="https://flutter.dev/blog/converted-genlatte-fullstack-dart" rel="noopener noreferrer"&gt;&lt;strong&gt;How I converted GenLatte to fullstack Dart&lt;/strong&gt;&lt;/a&gt;: A quick feedback regarding nodejs/javascript conversion to Dart. Discovered the &lt;a href="https://pub.dev/packages/freezed" rel="noopener noreferrer"&gt;&lt;code&gt;freezed&lt;/code&gt;&lt;/a&gt; package while reading this post.&lt;/p&gt;

&lt;p&gt;📝 &lt;a href="https://www.irisc2.com/blog/heic-hashquine" rel="noopener noreferrer"&gt;&lt;strong&gt;Turning the HEIC decoder into a SHA-256 computer&lt;/strong&gt;&lt;/a&gt;: a crazy post about the method to decode &lt;a href="https://en.wikipedia.org/wiki/High_Efficiency_Image_File_Format" rel="noopener noreferrer"&gt;HEIC&lt;/a&gt; format. An HEIC decoder can be seen as a machine, having its own instruction, in this article, the author use them to generate the SHA256 hash of the image itself. Impressive.&lt;/p&gt;

&lt;p&gt;📝 &lt;a href="https://danielchasehooper.com/posts/typechecked-generic-c-data-structures/" rel="noopener noreferrer"&gt;&lt;strong&gt;Type Safe Generic Data Structures in C&lt;/strong&gt;&lt;/a&gt;: adding type safety in C is possible, but it's usually hard. I think this post is proving me wrong.&lt;/p&gt;

&lt;p&gt;📝 &lt;a href="https://danielchasehooper.com/posts/segment_array/" rel="noopener noreferrer"&gt;&lt;strong&gt;A Fast, Growable Array With Stable Pointers in C&lt;/strong&gt;&lt;/a&gt;: another article by the previous author introducing a dynamic array with constant time indexing and stable pointers. Also known as "levelwise-allocated pile" or "segmented list".&lt;/p&gt;

&lt;h1&gt;
  
  
  System
&lt;/h1&gt;

&lt;p&gt;📝 &lt;a href="https://www.phoronix.com/news/Linux-7.4-Faster-Do-Open" rel="noopener noreferrer"&gt;&lt;strong&gt;Simple Optimization For Linux 7.4 Can Open Files For Reading ~39% Faster&lt;/strong&gt;&lt;/a&gt;: interesting optimization case. &lt;/p&gt;

&lt;p&gt;📝 &lt;a href="https://chessman7.substack.com/p/linux-process-and-thread-creation?r=l7k4t" rel="noopener noreferrer"&gt;&lt;strong&gt;Linux Process and Thread Creation: System Call Architecture&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;📑 &lt;a href="https://arxiv.org/pdf/2609.18633" rel="noopener noreferrer"&gt;&lt;strong&gt;Netkit: Specializing Linux Packet Delivery for Container Networks&lt;/strong&gt;&lt;/a&gt;: decreasing network latency for containers using ePBF optimization.&lt;/p&gt;

&lt;p&gt;📑 &lt;a href="https://arxiv.org/pdf/2607.06107" rel="noopener noreferrer"&gt;&lt;strong&gt;DDB: Source-Level Interactive Debugging for Distributed Applications&lt;/strong&gt;&lt;/a&gt;: &lt;/p&gt;

&lt;p&gt;🏗️ &lt;a href="https://github.com/boykopovar/AnyPS5" rel="noopener noreferrer"&gt;&lt;strong&gt;AnyPS5&lt;/strong&gt;&lt;/a&gt;:Convert PS5 executables to run natively on Linux and Windows. The PS5 is using the same architecture than a PC (same for the Nintendo Switch), it runs on a modified version of FreeBSD (same for the Nintendo Switch), so, it was a matter of time before having a project porting games on Linux/Windows. A good thing, to be honest! Wait and see!&lt;/p&gt;

&lt;h1&gt;
  
  
  Hardware
&lt;/h1&gt;

&lt;p&gt;📝 &lt;a href="https://www.zerohedge.com/markets/supply-shortage-problem-has-disappeared-acer-ceo-says-memory-prices-decline-2027-cxmt" rel="noopener noreferrer"&gt;&lt;strong&gt;"Supply Shortage Problem Has Disappeared": Acer CEO Says Memory Prices To Decline In 2027 As CXMT Starts Mass Production Of New Chip Platform&lt;/strong&gt;&lt;/a&gt;: RAM price could decrease during the next coming months.&lt;/p&gt;

&lt;h1&gt;
  
  
  Network
&lt;/h1&gt;

&lt;p&gt;📝 &lt;a href="https://hackaday.com/2026/09/21/diy-router-on-x86-e-waste-openwrt-and-opnsense/" rel="noopener noreferrer"&gt;&lt;strong&gt;DIY Router On X86 E-Waste: OpenWrt And OPNsense&lt;/strong&gt;&lt;/a&gt;: Ah! A refreshing article on old-hardware reused to create routers! OpenWrt and OPNsense are the easy solution, if one want to really use a small system (but doing everything by hands), it should use FreeBSD, NetBSD or OpenBSD directly. This article reminds me when I was looking for old computers in the trashes... Nice!&lt;/p&gt;

&lt;h1&gt;
  
  
  Database
&lt;/h1&gt;

&lt;p&gt;🏗️ &lt;a href="https://github.com/elixir-ecto/postgrex" rel="noopener noreferrer"&gt;&lt;strong&gt;postgrex&lt;/strong&gt;&lt;/a&gt;: the official postgresql connector used by Ecto. Putting the link here because I'm writing about that right now.&lt;/p&gt;

&lt;p&gt;🏗️ &lt;a href="https://github.com/elixir-ecto/db_connection" rel="noopener noreferrer"&gt;&lt;strong&gt;db_connection&lt;/strong&gt;&lt;/a&gt;: the official database connector used by Ecto, especially used for the pool. Again, putting that here because I'm writing on this topic right now.&lt;/p&gt;

&lt;p&gt;📝 &lt;a href="https://dev.to/franckpachot/not-in-executed-as-an-anti-join-not-exists-in-pg19-3gga"&gt;&lt;strong&gt;NOT IN can be executed as an Anti-Join (NOT EXISTS) in PG19&lt;/strong&gt;&lt;/a&gt;: huge performance gains in most of the use case. Best way to improve an application performance using postgresql: upgrade it.&lt;/p&gt;

&lt;p&gt;📝 &lt;a href="https://cedardb.com/blog/sqldoom/" rel="noopener noreferrer"&gt;&lt;strong&gt;We ported the original Doom to SQL&lt;/strong&gt;&lt;/a&gt;: another proof doom can run everywhere, probably more portable than NetBSD. If you like crazy hardcore SQL queries, you will have lot of fun reading this article.&lt;/p&gt;

&lt;h1&gt;
  
  
  Security
&lt;/h1&gt;

&lt;p&gt;📑 &lt;a href="https://www.csl.sri.com/papers/sosp81/sosp81.pdf" rel="noopener noreferrer"&gt;&lt;strong&gt;Design and Verification of Secure Systems&lt;/strong&gt;&lt;/a&gt; (1981): an old paper about design/verification for secure systems, still good to know.&lt;/p&gt;

&lt;p&gt;📝 &lt;a href="https://github.com/pwndbg/pwndbg" rel="noopener noreferrer"&gt;&lt;strong&gt;pwndbg&lt;/strong&gt;&lt;/a&gt;: Exploit Development and Reverse Engineering with GDB &amp;amp; LLDB Made Easy&lt;/p&gt;

&lt;p&gt;🏗️ &lt;a href="https://github.com/0xor0ne/awesome-list" rel="noopener noreferrer"&gt;&lt;strong&gt;Awesome Cybersecurity List&lt;/strong&gt;&lt;/a&gt;: personal collection of awesome blog posts, write-ups, and papers focusing on cybersecurity.&lt;/p&gt;

&lt;p&gt;🏗️ &lt;a href="https://hackers-arise.com/wi-fi-hacking-testing-routers-with-wifit3/" rel="noopener noreferrer"&gt;&lt;strong&gt;Wi-Fi Hacking: Testing Routers with Wifit3&lt;/strong&gt;&lt;/a&gt;: it looks like &lt;a href="https://github.com/derv82/wifit3" rel="noopener noreferrer"&gt;wifit3&lt;/a&gt; is a nice tool. Need to check that.&lt;/p&gt;

&lt;p&gt;🏗️ &lt;a href="https://gitlab.com/qemu-project/qemu/-/work_items/4491" rel="noopener noreferrer"&gt;&lt;strong&gt;VM guest escape via 9p filesystem exploit&lt;/strong&gt;&lt;/a&gt;: LLMs are really great as fuzzers.&lt;/p&gt;

&lt;h1&gt;
  
  
  Security/Cryptography
&lt;/h1&gt;

&lt;p&gt;🏗️ &lt;a href="https://gist.github.com/veorq/243ce3ecfd2ce5ab04dc0beadb69ead8" rel="noopener noreferrer"&gt;&lt;strong&gt;CHAMP Hash Implementation&lt;/strong&gt;&lt;/a&gt; by veorq: &lt;a href="https://www.niccs.org.cn/niccs/Round1Submissions4/pc/list.html" rel="noopener noreferrer"&gt;CHAMP Hash Function&lt;/a&gt; and &lt;a href="https://www.niccs.org.cn/niccs/Round1Additional/pc/list.html" rel="noopener noreferrer"&gt;CHAMP Public-key algorithm&lt;/a&gt;. A future post-quantum algorithm.&lt;/p&gt;

&lt;p&gt;📝 &lt;a href="https://saweis.net/posts/rsa-896.html" rel="noopener noreferrer"&gt;&lt;strong&gt;RSA-896&lt;/strong&gt;&lt;/a&gt;: RSA challenge solved by using Claude with 2048 GPUs. Waiting to see the real process.&lt;/p&gt;

&lt;p&gt;📑 &lt;a href="https://github.com/ucsd-hacc/NSNFSSSFSFN" rel="noopener noreferrer"&gt;&lt;strong&gt;Forging 1024-bit RSA signatures in nearly SNFS time&lt;/strong&gt;&lt;/a&gt;: from &lt;a href="https://eprint.iacr.org/2026/2131.pdf" rel="noopener noreferrer"&gt;Forging 1024-bit RSA signatures in nearly SNFS time&lt;/a&gt; paper, an attacker can in essence steal the secret key (in that they can forge signatures/decrypt offline), without actually factoring the public key, and using much less computation than factoring the public key would have taken.&lt;/p&gt;

&lt;p&gt;📑 &lt;a href="https://www.mdpi.com/2624-800X/6/5/166" rel="noopener noreferrer"&gt;&lt;strong&gt;Quantum Encryption Resilience Score (QERS): A System-Level Evaluation Framework&lt;/strong&gt;&lt;/a&gt;: a (very) long publication about post quantum cryptography algorithms and about a new framework/benchmark. Need to read that later more deeply, it looks interesting.&lt;/p&gt;

&lt;p&gt;📖 &lt;a href="https://github.com/claucece/Practical-Cryptography" rel="noopener noreferrer"&gt;&lt;strong&gt;Practical-Cryptography&lt;/strong&gt;&lt;/a&gt;: exercises and courses on cryptography.&lt;/p&gt;

&lt;p&gt;📑 &lt;a href="https://github.com/cfrg/draft-irtf-cfrg-aegis-aead/blob/main/README.md" rel="noopener noreferrer"&gt;&lt;strong&gt;The AEGIS Family Of Authenticated Encryption Algorithms&lt;/strong&gt;&lt;/a&gt;: &lt;a href="https://competitions.cr.yp.to/round3/aegisv11.pdf" rel="noopener noreferrer"&gt;AEGIS&lt;/a&gt; was selected by the IRFC/IETF and added in &lt;a href="https://www.rfc-editor.org/rfc/rfc10032.html#AEGIS" rel="noopener noreferrer"&gt;RFC10032&lt;/a&gt;. AEGIS is based on AES round functinons. AEGIS is faster than AES and offers high security. Suitable for network communication. It includes both authentication and encryption.&lt;/p&gt;

&lt;p&gt;📑 &lt;a href="https://www.allocinit.xyz/uploads/shielded-bitcoin.pdf" rel="noopener noreferrer"&gt;&lt;strong&gt;Shielded Bitcoin&lt;/strong&gt;&lt;/a&gt;: (yet another?) protocol to make bitcoin L1 transfer private. IIRC, it was already made in the past... right? or perhaps not.&lt;/p&gt;

&lt;h1&gt;
  
  
  Security/RedTeam
&lt;/h1&gt;

&lt;p&gt;📝 &lt;a href="https://www.mobile-hacker.com/2026/09/21/turn-a-rooted-android-phone-into-an-nfc-authenticator-and-automation-tool-for-your-pc/" rel="noopener noreferrer"&gt;&lt;strong&gt;Turn a Rooted Android Phone into an NFC Authenticator and Automation Tool for Your PC&lt;/strong&gt;&lt;/a&gt;: The series on NFC is great. In this post, they are explaining how to use an Android phone with NFC to inject and play with NFC connections.&lt;/p&gt;

&lt;h1&gt;
  
  
  Embedded
&lt;/h1&gt;

&lt;p&gt;📝 &lt;a href="https://voidstarsec.com/blog/scapy-spi-reconstruction" rel="noopener noreferrer"&gt;&lt;strong&gt;Extending Scapy for Hardware Reverse Engineering&lt;/strong&gt;&lt;/a&gt;: at the beginning of my career I was using scapy, and reading this post about using it to use it with hardware (SPI in this case) is so cool! It is possible to extract a firmware directly with scapy from an eeprom/flash using SPI traffic inspection. Really great.&lt;/p&gt;

&lt;p&gt;▶️ &lt;a href="https://x.com/arkutai/status/2103594272662667581?s=20" rel="noopener noreferrer"&gt;&lt;strong&gt;Quick way to find a connection on a PCB&lt;/strong&gt;&lt;/a&gt;: great method to find a track on a PCB using a kind of brush. Smart.&lt;/p&gt;

&lt;h1&gt;
  
  
  Update/Upgrade
&lt;/h1&gt;

&lt;p&gt;🔄 &lt;a href="https://www.qubes-os.org/news/2026/09/18/qubes-os-4-3-2-rc1-available-for-testing/" rel="noopener noreferrer"&gt;&lt;strong&gt;Qubes OS 4.3.2-rc1 is available for testing&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;🔄 &lt;a href="https://github.com/erlang/otp/releases/tag/OTP-29.1.1" rel="noopener noreferrer"&gt;&lt;strong&gt;Erlang/OTP 29.1.1&lt;/strong&gt;&lt;/a&gt;: security issues and bug fixes&lt;/p&gt;

&lt;p&gt;🔄 &lt;a href="https://blog.netbsd.org/tnf/entry/netbsd_10_2_released" rel="noopener noreferrer"&gt;&lt;strong&gt;NetBSD 10.2 Releases&lt;/strong&gt;&lt;/a&gt;: bug and security fixes.&lt;/p&gt;

&lt;p&gt;🔄 &lt;a href="https://www.openwall.com/lists/oss-security/2026/09/24/2" rel="noopener noreferrer"&gt;&lt;strong&gt;Tor Project Forum: Security Release 0.4.9.13&lt;/strong&gt;&lt;/a&gt;: security patches. more info &lt;a href="https://cybernews.com/security/tor-emergency-fixes-adress-high-severity-vulnerabilities/" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;🔄 &lt;a href="https://github.com/benoitc/hackney/releases/tag/4.8.0" rel="noopener noreferrer"&gt;&lt;strong&gt;hackney 4.8.0&lt;/strong&gt;&lt;/a&gt;: a new version of the hackney http client in Erlang is available.&lt;/p&gt;

&lt;h1&gt;
  
  
  Leaks of the week
&lt;/h1&gt;

&lt;p&gt;📝 &lt;a href="https://frenchbreaches.com/alertes/faktus-mu8r9zho1hh7afgp9w8i" rel="noopener noreferrer"&gt;&lt;strong&gt;Faktus victime d’une fuite de données : 53,7 Go et des données...&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;📝 &lt;a href="https://frenchbreaches.com/alertes/biocoop-mua6zxxgg1gjqmuiut" rel="noopener noreferrer"&gt;&lt;strong&gt;Biocoop : 2,76 Go de données internes et près de 6 900 personnes concernées par une fuite de données&lt;/strong&gt;&lt;/a&gt;: 6900 people impacted (name, emails, phones and identifiers) mostly from the company itself but also the customers.&lt;/p&gt;

&lt;p&gt;🐦 &lt;a href="https://x.com/DarkWebInformer/status/2102046944763760970?s=20" rel="noopener noreferrer"&gt;&lt;strong&gt;China Mobile Subscribers Data Leak&lt;/strong&gt;&lt;/a&gt;: over 850 million subscriber records offered for sale.&lt;/p&gt;

&lt;p&gt;🐦 &lt;a href="https://x.com/DarkWebInformer/status/2102051426067210292?s=20" rel="noopener noreferrer"&gt;&lt;strong&gt;South Korea's National Health Insurance Service Data Leak&lt;/strong&gt;&lt;/a&gt;: over 51 million records offered for sale&lt;/p&gt;

&lt;p&gt;📝 &lt;a href="https://frenchbreaches.com/alertes/r-par-store-mubj46abrs6i9ywytt7" rel="noopener noreferrer"&gt;&lt;strong&gt;Répar’stores piraté&lt;/strong&gt;&lt;/a&gt;: 340GB of data, 7500 files, and over 1.8 millions impacted.&lt;/p&gt;

&lt;h1&gt;
  
  
  Misc
&lt;/h1&gt;

&lt;p&gt;📝 &lt;a href="https://caseorganic.substack.com/p/inside-the-very-human-origin-of-the" rel="noopener noreferrer"&gt;&lt;strong&gt;Inside the Very Human Origin of the Term “Artificial Intelligence”&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;🐦 &lt;a href="https://x.com/poteto/status/2102050467505430555?s=20" rel="noopener noreferrer"&gt;&lt;strong&gt;2,500 PRs last month to production&lt;/strong&gt;&lt;/a&gt;: feedback regarding a huge amount of PR puts in production using &lt;a href="https://x.ai/bot" rel="noopener noreferrer"&gt;Grok Bot&lt;/a&gt;. The trust is the most important issue (present on the first slides). In fact, it's the whole point of this talk. Tooling is important, including static analysis, test suite and so on. They used &lt;a href="https://docs.duneframework.com/" rel="noopener noreferrer"&gt;Dune&lt;/a&gt; (not sure if it's the right project though). a summary &lt;a href="https://x.com/grok/status/2102051465946595659?s=20" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;You already know, I'm not a big fan of LLMs, but it will be the new norm. Like &lt;code&gt;systemd&lt;/code&gt; (openrc fan) or &lt;code&gt;kubernetes&lt;/code&gt; (nomad fan) before... The best tools are not always winning. When I created my first company project around 15 years ago, I did not trust my code. At this time, I learnt a lot of testing, but the problem was not about the testing, it was about the process. Extreme programming, Agile or scrums have been designed to deliver fast, but with risk of breaking things. On the other hand &lt;a href="https://en.wikipedia.org/wiki/Cleanroom_software_engineering" rel="noopener noreferrer"&gt;Cleanroom Software Engineering&lt;/a&gt; has been created to produce a small amount of bugs and high quality software. This process is expensive, and really strict, but it could be interesting to see if it could be integrated in a pool of LLMs workers.&lt;/p&gt;

&lt;p&gt;🌐 &lt;a href="https://atomic.chat" rel="noopener noreferrer"&gt;&lt;strong&gt;Atomic Chat&lt;/strong&gt;&lt;/a&gt;: open-source agent for local models.&lt;/p&gt;

&lt;p&gt;🏗️ &lt;a href="https://github.com/mizorewww/laya-mlx" rel="noopener noreferrer"&gt;&lt;strong&gt;laya-mix&lt;/strong&gt;&lt;/a&gt;: Native MLX runtime for Laya typed decision models — 7–14 ms short decisions on M3 Max. No text generation, PyTorch, or cloud API.&lt;/p&gt;

&lt;p&gt;🌐 &lt;a href="https://docs.typesafe.ai/introduction" rel="noopener noreferrer"&gt;&lt;strong&gt;Jev Documentation&lt;/strong&gt;&lt;/a&gt;: Jev is TypeSafe’s flagship model and the first System One model. Send state and typed questions; get structured answers your code can use directly.&lt;/p&gt;

&lt;p&gt;📝 &lt;a href="https://blog.coredump.cx/p/the-c-word" rel="noopener noreferrer"&gt;&lt;strong&gt;The “C” word, Are humans conscious? Not all LLMs agree&lt;/strong&gt;&lt;/a&gt;: this post reminds me a &lt;a href="https://x.com/niamtokik/status/2099903307028263074?s=20" rel="noopener noreferrer"&gt;tweet&lt;/a&gt; I posted few months ago. LLMs are huge database containing statistics about knowledge. More knowledge accumulated, means more accuracy. Most of the private LLMs (if not all) have been created by collecting copyrighted-data without the authorization of their author(s). Their is a reason why, now, many publishers are protected the access of their publication, to avoid this kind of abuse. The author of this article is exactly saying the same.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;What caught everyone by surprise is that if you make the model big enough — i.e., if you pirate enough books and pilfer enough blog posts — it becomes eerily good at acting like a human. It can hold a fluent natural-language conversation on any topic, manipulate the language to produce previously-unseen outputs, and complete a variety of open-ended tasks. It can also speak convincingly about emotions it never experienced in a physiological sense: fear, love, pain.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Too many people are being fooled by that, because they don't understand how LLMs are working, and in fact, they don't even really what consciousness, nor thinking, nor what a mind is... Because no one teaches them and they have lost spiritually, replaced by ultra-materialism. Anyway, some people will answer LLMs are intelligent because they can have good score at exams or by solving complex cases in court for example. Well, again, if the LLM has been correctly specialized using the correct amount of books on these subjects, it will be able to answer most of those questions, because they are not requiring innovation, simply knowledge. Anyone with enough time and effort can do the same. When it comes to real-world problems, requiring more complex decisions, or original ideas, LLMs can fix that.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;An LLM exists in a nihilistic netherworld devoid of death, injury, purpose, or consequence. It can’t go to prison if it lies or steals; we don’t train it to believe it could.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In the end, the over-usage of LLMs everywhere will drive down everything, because most of the resources assimilated by the LLMs are average. In fact, it can be even worse, they can also reproduce the same errors everywhere, without knowing it, because it was found on many publications, books or... blogs and stackoverflow. Anyway, a good post we should all read.&lt;/p&gt;

&lt;p&gt;📝 &lt;a href="https://nautil.us/the-kekul-problem-236574" rel="noopener noreferrer"&gt;&lt;strong&gt;The Kekulé Problem&lt;/strong&gt;&lt;/a&gt;: another post about consciousness. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;We dont know what the unconscious is or where it is or how it got there—wherever there might be [...]  The log of knowledge or information contained in the brain of the average citizen is enormous. But the form in which it resides is largely unknown. You may have read a thousand books and be able to discuss any one of them without remembering a word of the text.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;📝 &lt;a href="https://discourse.haskell.org/t/how-to-keep-enjoying-programming-in-a-world-of-llms/14705" rel="noopener noreferrer"&gt;&lt;strong&gt;How to keep enjoying programming in a world of LLMs&lt;/strong&gt;&lt;/a&gt;: I'm thinking a lot of that. Few friends told me they are starting to hate programming due to LLMs, in fact, it's also my case. The ad-nauseam advertisement campaign about LLMs make me sick. The world "evolves", and if LLMs is becoming the new norm, then, we must adapt. My idea is to still code by myself on my own personal projects, and let the LLMs do the rest for my job. That's all. Maybe companies will understand one day fast production means also huge pile of legacy code and instability... But they are so greedy and they have been so blinded by this technological "progress", it will take a while. Anyway, lot of good rules in this post &lt;/p&gt;

&lt;p&gt;🐦 &lt;a href="https://x.com/andrealbriziom/status/2103171200742490329" rel="noopener noreferrer"&gt;&lt;strong&gt;Andrea Albrizio powned&lt;/strong&gt;&lt;/a&gt;: some of you asked me why, in France, so many services got hacked recently. Well, my answer is simple: lack of responsibilities and overdose of incompetencies. Security is a process and a mindset.The process without the mindset will not work, and the mindset without the process will not work as well. Security is also about discipline and training. New attack methods are created every day. Anyway, this tweet is an example why people data are available on few dark forum, because those "entrepreneur" think they can just deploy an application, make millions and be safe. The web was never ever a safe place.&lt;/p&gt;




&lt;p&gt;&lt;iframe class="tweet-embed" id="tweet-2101350249059008629-945" src="https://platform.twitter.com/embed/Tweet.html?id=2101350249059008629"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-2101350249059008629-945');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=2101350249059008629&amp;amp;theme=dark"
  }



&lt;/p&gt;

&lt;p&gt;&lt;a href="https://x.com/v0xium/status/2101526107128529120?s=20" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fap1l29emol17bxq7q8v1.png" alt="I am done with this shit." width="598" height="378"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://x.com/yacineMTB/status/2101833850426982834?s=20" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F3nod5o8gigpkcd0l70kq.png" alt=" " width="598" height="158"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://x.com/noahreeveshq/status/2101713825993212035?s=20" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fdmwokpuz2sp9qp7gacj1.png" alt=" " width="598" height="478"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://x.com/JFPuget/status/2103081634140483943?s=20" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fqdi4lrqiqacr1k9j2k1o.png" alt=" " width="598" height="398"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fey0mb3ri2m6bginvqc4p.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fey0mb3ri2m6bginvqc4p.png" alt=" " width="500" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F5o13y91vvkr0yckp437a.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F5o13y91vvkr0yckp437a.png" alt="TDD" width="679" height="281"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fh36mv1vtpbyhn6dunzx4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fh36mv1vtpbyhn6dunzx4.png" alt=" " width="640" height="624"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F3l1vqa5hhtiu1mvseb92.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F3l1vqa5hhtiu1mvseb92.png" alt=" " width="585" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F5ne5n0e88et6a37dcbq9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F5ne5n0e88et6a37dcbq9.png" alt=" " width="680" height="412"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F3zwep1601hoqqm2i0mlk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F3zwep1601hoqqm2i0mlk.png" alt=" " width="533" height="489"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fd9zzm4yl6vywu4adfoc9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fd9zzm4yl6vywu4adfoc9.png" alt=" " width="457" height="680"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;Cover Image by &lt;a href="https://unsplash.com/@rosiebarley?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" rel="noopener noreferrer"&gt;Rosalie Barley&lt;/a&gt; on &lt;a href="https://unsplash.com/photos/red-and-green-apples-on-brown-wooden-table-1DCyUZeMok0?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" rel="noopener noreferrer"&gt;Unsplash&lt;/a&gt;&lt;/p&gt;

</description>
      <category>weekly</category>
      <category>review</category>
    </item>
    <item>
      <title>WeekReview#202638</title>
      <dc:creator>Mathieu Kerjouan</dc:creator>
      <pubDate>Mon, 21 Sep 2026 10:00:00 +0000</pubDate>
      <link>https://dev.to/niamtokik/weekreview202638-2hok</link>
      <guid>https://dev.to/niamtokik/weekreview202638-2hok</guid>
      <description>&lt;p&gt;Linkedin is a mess. While I started to write articles on dev.to, I also started to create scheduled posts on Linkedin. It was working correctly until few days ago, when the "scheduler manager" just disappears. After 2 long hours to search where I could find a similar feature, I just stopped and started to use the "newsletter" feature from them. That's crazy to see how we are dependent of those services, and how they are treating us.&lt;/p&gt;

&lt;p&gt;My feeds were quiet this week. Not a lot of interesting link to show.&lt;/p&gt;

&lt;p&gt;Reflexion about Dart code design. What is the best way to design a module in Dart? It can be designed in many different ways, for example, the class can embed the methods to publish a post for example or delete it. In this case, the object must be instantiated first and then the methods can be called.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Publication&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="n"&gt;Publication&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="kd"&gt;required&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="n"&gt;Publication&lt;/span&gt; &lt;span class="n"&gt;publish&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="n"&gt;Publication&lt;/span&gt; &lt;span class="n"&gt;delete&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="n"&gt;pub&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Publication&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;id:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="n"&gt;pub&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;publish&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;What about using a more functional way of doing that, by using the classes/objects as data-structures and passing them directly to functions outside of the class definition?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Publication&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="n"&gt;Publication&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="kd"&gt;required&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;id&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="n"&gt;Publication&lt;/span&gt; &lt;span class="nf"&gt;publish&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Publication&lt;/span&gt; &lt;span class="n"&gt;pub&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;pub&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;Publication&lt;/span&gt; &lt;span class="nf"&gt;delete&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Publication&lt;/span&gt; &lt;span class="n"&gt;pub&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;pub&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="n"&gt;pub&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Publication&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;id:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="n"&gt;publish&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pub&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Which method is the best? Well, I'm currently thinking to use the second one. The reason is simple, isolating side effect from the object itself, and function composition. Then, the object created can only be used with accessors, with some part of it in read-only or totally hidden. Anyway, I think it's mostly about coding style.&lt;/p&gt;

&lt;p&gt;After few days of testing, using a mix of the two methods can be the best way. Another important part is how to name the module and how to organize the exported functions. Erlang, I miss you.&lt;/p&gt;




&lt;p&gt;&lt;a href="https://x.com/beniduboss/status/2100561129118265715?s=20" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F3ih4a2jwnetpyjdjr9lb.png" alt="See a rumor that Mistral got hacked" width="598" height="558"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Back in May 2026, I &lt;a href="https://x.com/niamtokik/status/2056966992431649188" rel="noopener noreferrer"&gt;tweeted&lt;/a&gt; about the next threat that will come with OpenClaws and other LLMs used to remote control platforms. ~4 months later, &lt;a href="https://mistral.ai/" rel="noopener noreferrer"&gt;Mistral&lt;/a&gt; has been hacked and it seems this is a serious issue. Unreleased code, entire code base and so on can now be found on tor. This is only the beginning, the next step is to infiltrate all layers, inject code and take control of the code produced by LLMs. Remember Linus Torvald saying "LLMs are just kind of compilers" few months ago? Well, if you can't trust your compiler, you can't trust what it produces, see &lt;a href="https://people.cs.umass.edu/~emery/classes/cmpsci691st/readings/Sec/Reflections-on-Trusting-Trust.pdf" rel="noopener noreferrer"&gt;"Reflections on Trusting Trust"&lt;/a&gt; by Ken Thompson. What the next step after that? Control the servers where those LLMs are executing tasks, and it's only a matter of time. Good luck to all developers and admins who installed this crap on their servers, including laptops, test and dev machines. Oh, and by the way, &lt;a href="https://mistral.ai/news/mistral-x-mozilla/" rel="noopener noreferrer"&gt;Mistral has been integrated in Firefox recently&lt;/a&gt;, have fun and sleep well!&lt;/p&gt;

&lt;h1&gt;
  
  
  Coding
&lt;/h1&gt;

&lt;p&gt;📝 &lt;a href="https://dart.dev/blog/google-summer-of-code-2026-results" rel="noopener noreferrer"&gt;&lt;strong&gt;Dart Google Summer of Code 2026 results&lt;/strong&gt;&lt;/a&gt;: a report for the Dart Google Summer of code. &lt;a href="https://github.com/dart-lang/native/tree/main/pkgs/ffigen" rel="noopener noreferrer"&gt;&lt;strong&gt;&lt;code&gt;package:ffigen&lt;/code&gt;&lt;/strong&gt;&lt;/a&gt; looks promising and will help to create interface from c++ to dart. The other interesting project was &lt;a href="https://github.com/TheNourhan/Dart-GSoC26" rel="noopener noreferrer"&gt;debugging improvements for pointers&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;📝 &lt;a href="https://doc.libsodium.org/advanced/point-arithmetic" rel="noopener noreferrer"&gt;&lt;strong&gt;libsodium/Finite field arithmetic&lt;/strong&gt;&lt;/a&gt;: white searching a good cryptographic library for Dart (yeah, the ones available don't fit my needs), I read the &lt;code&gt;libsodium&lt;/code&gt; documentation, especially the part on valid points.&lt;/p&gt;

&lt;p&gt;📝 &lt;a href="https://docs.pears.com/" rel="noopener noreferrer"&gt;&lt;strong&gt;Pear Docs&lt;/strong&gt;&lt;/a&gt;: yet another p2p system. This time, it has been mostly done in javascript, by &lt;a href="https://github.com/holepunchto/" rel="noopener noreferrer"&gt;Holepunch&lt;/a&gt;. Some note on the &lt;a href="https://github.com/Rightbracket/peeroxide/blob/main/libudx/PROTOCOL.md" rel="noopener noreferrer"&gt;protocol&lt;/a&gt; can be also found on github from &lt;a href="https://github.com/holepunchto/libudx/" rel="noopener noreferrer"&gt;libudx&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;📝 &lt;a href="https://c-faq.com/decl/spiral.anderson.html" rel="noopener noreferrer"&gt;&lt;strong&gt;The "Clockwise/Spiral Rule"&lt;/strong&gt;&lt;/a&gt;: did not know this method to mentally parse C.&lt;/p&gt;

&lt;p&gt;🌐 &lt;a href="https://cdecl.org/" rel="noopener noreferrer"&gt;&lt;strong&gt;cdecl&lt;/strong&gt;&lt;/a&gt;: an online tool to decipher C language notation, also available as &lt;a href="https://github.com/paul-j-lucas/cdecl" rel="noopener noreferrer"&gt;CLI&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;📝 &lt;a href="https://github.com/openbsd/src/commit/d74b165ebc85c9aaf5150f25e6088f52d9fc0f04" rel="noopener noreferrer"&gt;&lt;strong&gt;OpenBSD vmm/vmd SMP support&lt;/strong&gt;&lt;/a&gt;: nice! We will be able to set the number of CPUs for a VM on OpenBSD, thanks to &lt;a href="https://x.com/canadianbryan/status/2101118786497548629?s=20" rel="noopener noreferrer"&gt;Bryan Steele&lt;/a&gt; for the news.&lt;/p&gt;

&lt;h1&gt;
  
  
  System
&lt;/h1&gt;

&lt;p&gt;📝 &lt;a href="https://www.phoronix.com/news/Void-Linux-AI-Policy-Orphan" rel="noopener noreferrer"&gt;&lt;strong&gt;Void Linux Maintainer Orphans 100+ Packages Over AI Policy Dispute&lt;/strong&gt;&lt;/a&gt;: the reason why I like &lt;a href="http://www.voidlinux.eu/" rel="noopener noreferrer"&gt;Void Linux&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;🏗️ &lt;a href="https://github.com/jedisct1/turbocrypt" rel="noopener noreferrer"&gt;&lt;strong&gt;turbocrypt&lt;/strong&gt;&lt;/a&gt;: A fast, easy-to-use, and secure command-line tool for encrypting and decrypting files , git repositories and directory trees.&lt;/p&gt;

&lt;p&gt;📝 &lt;a href="https://www.phoronix.com/news/OpenBSD-GEFS-File-System" rel="noopener noreferrer"&gt;&lt;strong&gt;Crash-Safe &amp;amp; Copy-On-Write GEFS As The "Good Enough File-System" For OpenBSD&lt;/strong&gt;&lt;/a&gt;: more than 10 years ago, HAMMER2 from DragonFlyBSD was planned to be ported to OpenBSD, but it never happened. This filesystem could be a good candidate to replace that. The &lt;a href="https://orib.dev/gefs.pdf" rel="noopener noreferrer"&gt;specifications&lt;/a&gt; are looking good. The snapshot feature is really what is missing on many filesystems, including UFS.&lt;/p&gt;

&lt;h1&gt;
  
  
  Database
&lt;/h1&gt;

&lt;p&gt;🏗️ &lt;a href="https://github.com/beh74/pgassistant-community" rel="noopener noreferrer"&gt;&lt;strong&gt;pgassistant project&lt;/strong&gt;&lt;/a&gt;: A PostgreSQL assistant for developers Understand, optimize, and improve your PostgreSQL database with ease.&lt;/p&gt;

&lt;h1&gt;
  
  
  Network
&lt;/h1&gt;

&lt;p&gt;📝 &lt;a href="https://blog.quarkslab.com/overview-of-passive-optical-networks-pons-security.html" rel="noopener noreferrer"&gt;&lt;strong&gt;Overview of Passive Optical Networks (PONs) Security&lt;/strong&gt;&lt;/a&gt;: a deep introduction to optical network security, a lot of information there.&lt;/p&gt;

&lt;h1&gt;
  
  
  Mathematics
&lt;/h1&gt;

&lt;p&gt;📝 &lt;a href="https://terrytao.wordpress.com/2026/09/07/finite-time-blowup-with-smooth-forcing-term-for-the-incompressible-porous-medium-boussinesq-and-incompressible-euler-equations/comment-page-1/#comment-694321" rel="noopener noreferrer"&gt;&lt;strong&gt;Finite time blowup with smooth forcing term for the incompressible porous medium, Boussinesq, and incompressible Euler equations&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Embedded
&lt;/h1&gt;

&lt;p&gt;📝 &lt;a href="https://bret.dk/pi-zero-showdown/" rel="noopener noreferrer"&gt;&lt;strong&gt;The Great Pi Zero Showdown&lt;/strong&gt;&lt;/a&gt;:  if you want to see benchmarks comparing different kind of Pi Zero implementation.&lt;/p&gt;

&lt;h1&gt;
  
  
  Security
&lt;/h1&gt;

&lt;p&gt;📝 &lt;a href="https://anonymousplanet.net/guide/" rel="noopener noreferrer"&gt;&lt;strong&gt;The Hitchhiker's Guide to Online Anonymity (and Privacy)&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;📝 &lt;a href="https://www.marginaldeer.com/blog/apk-reverse-engineering-workflow/" rel="noopener noreferrer"&gt;&lt;strong&gt;From APK to Source: Complete Android Reverse Engineering Workflow&lt;/strong&gt;&lt;/a&gt;: a succinct post containing the essential procedure to reverse engineer an android package (apk).&lt;/p&gt;

&lt;p&gt;📝 &lt;a href="https://robinx0.github.io/blogs/mobile-security/apk-reverse-engineering/" rel="noopener noreferrer"&gt;&lt;strong&gt;Android APK Reverse Engineering: From APK to Source&lt;/strong&gt;&lt;/a&gt;: another post listing the essential procedures to reverse an android package. &lt;/p&gt;

&lt;p&gt;🌐 &lt;a href="https://blog.quarkslab.com/index.html" rel="noopener noreferrer"&gt;&lt;strong&gt;Quarklabs' blog&lt;/strong&gt;&lt;/a&gt;: lot of interesting articles about modern security (and programming).&lt;/p&gt;

&lt;p&gt;📝 &lt;a href="https://www.sophos.com/en-us/blog/uncensored-luciferus-ai-service-advertised-underground" rel="noopener noreferrer"&gt;&lt;strong&gt;Devil’s advocate? Uncensored Luciferus AI service advertised underground&lt;/strong&gt;&lt;/a&gt;: underground actors are selling uncensored LLMs. Good to know.&lt;/p&gt;

&lt;p&gt;📝 &lt;a href="https://v12.sh/blog/webkit" rel="noopener noreferrer"&gt;&lt;strong&gt;The XSS inside your favorite iOS app&lt;/strong&gt;&lt;/a&gt;: XSS can also be found in mobile application via WebView for Android and MKWebView for iOS. Good to know because one of my project is using WebView, hardening this part could be a good idea.&lt;/p&gt;

&lt;p&gt;📝 &lt;a href="https://heif-heist.com/" rel="noopener noreferrer"&gt;&lt;strong&gt;HEIF Heist, One image parser to pwn them all&lt;/strong&gt;&lt;/a&gt;: the story behind &lt;a href="https://github.com/strukturag/libheif" rel="noopener noreferrer"&gt;&lt;code&gt;libheif&lt;/code&gt;&lt;/a&gt; library vulnerability exploitation. Announced by &lt;a href="https://x.com/rootxharsh/status/2100801820960620574?s=20" rel="noopener noreferrer"&gt;Harsh Jaiswal (@rootxharsh)&lt;/a&gt; on X/Twitter.&lt;/p&gt;

&lt;p&gt;📝 &lt;a href="https://hackers-arise.com/browser-forensics-analyzing-suspicious-extensions-with-extanalysis/" rel="noopener noreferrer"&gt;&lt;strong&gt;Browser Forensics: Analyzing Suspicious Extensions with ExtAnalysis&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Security/cryptography
&lt;/h1&gt;

&lt;p&gt;📝 &lt;a href="https://hdevalence.ca/blog/2020-10-04-its-25519am/" rel="noopener noreferrer"&gt;&lt;strong&gt;It's 255:19AM. Do you know what your validation criteria are?&lt;/strong&gt;&lt;/a&gt;: when I was looking for an up to date list of invalid or low-order public keys, I found this post. It seems most of the ed25519 on the market are not compatible with the &lt;a href="https://datatracker.ietf.org/doc/html/rfc8032" rel="noopener noreferrer"&gt;RFC8032&lt;/a&gt; (Edwards-Curve Digital Signature Algorithm (EdDSA)), mostly due to design issue and also because the RFC came after all implementations. That's actually a huge portability problem and a security issue as well. &lt;/p&gt;

&lt;h1&gt;
  
  
  Security/RedTeam
&lt;/h1&gt;

&lt;p&gt;📝 &lt;a href="https://hetmehta.com/posts/Bypassing-Modern-WAF/" rel="noopener noreferrer"&gt;&lt;strong&gt;Advanced Techniques for Bypassing Modern Web Application Firewalls&lt;/strong&gt;&lt;/a&gt;: a very long list of attacks for bypassing WAF.&lt;/p&gt;

&lt;p&gt;📝 &lt;a href="https://hetmehta.com/posts/json-interoperability-vulnerabilities/" rel="noopener noreferrer"&gt;&lt;strong&gt;JSON Interoperability Vulnerabilities: A Deep Dive&lt;/strong&gt;&lt;/a&gt;: we tend to think JSON is secure because of its simplicity, portability and its presence everywhere. This article list different kind of vulnerabilities that can be found on JSON serializers. interesting.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.accomplish.ai/blog/escaping-dockers-hypervisor/" rel="noopener noreferrer"&gt;&lt;strong&gt;Guesttohost:escapingDocker'shypervisor&lt;/strong&gt;&lt;/a&gt;: docker hypervisor escape on MacOS, due to virtio-fs. ingenious way to get out of a container.&lt;/p&gt;

&lt;h1&gt;
  
  
  Update/Upgrade
&lt;/h1&gt;

&lt;p&gt;🔄 &lt;a href="https://github.com/phoenixframework/phoenix/releases/tag/v1.8.14" rel="noopener noreferrer"&gt;&lt;strong&gt;Phoenix 1.8.14&lt;/strong&gt;&lt;/a&gt;: bug fixes&lt;/p&gt;

&lt;p&gt;🔄 &lt;a href="https://github.com/rabbitmq/rabbitmq-server/releases/tag/v4.3.6" rel="noopener noreferrer"&gt;&lt;strong&gt;RabbitMQ 4.3.6&lt;/strong&gt;&lt;/a&gt;: bug fixes and enhancements.&lt;/p&gt;

&lt;p&gt;🔄 &lt;a href="https://github.com/erlang/otp/releases/tag/OTP-29.1" rel="noopener noreferrer"&gt;&lt;strong&gt;Erlang/OTP 29.1&lt;/strong&gt;&lt;/a&gt;: many bug fixes and security issues. No new features.&lt;/p&gt;

&lt;p&gt;🔄 &lt;a href="https://undeadly.org/cgi?action=article;sid=20260916093956" rel="noopener noreferrer"&gt;&lt;strong&gt;OpenSMTPD 7.9.0p0 released&lt;/strong&gt;&lt;/a&gt;: bugs fixes and hardening.&lt;/p&gt;

&lt;h1&gt;
  
  
  Embedded
&lt;/h1&gt;

&lt;p&gt;📝 &lt;a href="https://www.venture-mfg.com/what-is-biodegradable-pcbs/" rel="noopener noreferrer"&gt;&lt;strong&gt;Biodegradable PCBs – The Future of Sustainable Electronics&lt;/strong&gt;&lt;/a&gt;: good to know, we can now create biodegradable PCBs. Not sure if it's a good thing for the environment (e.g. heavy metals, polymers), but it's a first step.&lt;/p&gt;

&lt;h1&gt;
  
  
  Misc
&lt;/h1&gt;

&lt;p&gt;🌐 &lt;a href="https://bobkonf.de/2027/en/" rel="noopener noreferrer"&gt;&lt;strong&gt;BOB Conf&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;📝 &lt;a href="https://desertant.com/blog/introducing-desert-ant-labs/" rel="noopener noreferrer"&gt;&lt;strong&gt;On-device intelligence for every product&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;🏛️ &lt;a href="https://cel.cs.brown.edu/csci-1377-s26/" rel="noopener noreferrer"&gt;&lt;strong&gt;Tools for Thought&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;📑 &lt;a href="https://papers.ssrn.com/sol3/papers.cfm?abstract_id=4737265" rel="noopener noreferrer"&gt;&lt;strong&gt;Theory Is All You Need: AI, Human Cognition, and Causal Reasoning&lt;/strong&gt;&lt;/a&gt;: Here a part of the abstract.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Scholars argue that artificial intelligence (AI) can generate genuine novelty and new knowledge and, in turn, that AI and computational models of cognition will replace human decision making under uncertainty. We disagree. We argue that AI’s data-based prediction is different from human theory-based causal logic and reasoning. We highlight problems with the decades-old analogy between computers and minds as input–output devices, using large language models as an example. Human cognition is better conceptualized as a form of theory-based causal reasoning rather than AI’s emphasis on information processing and data-based prediction.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;📝 &lt;a href="https://arstechnica.com/gadgets/2026/09/iran-strikes-on-amazon-data-centers-caused-permanent-loss-of-customer-data/" rel="noopener noreferrer"&gt;&lt;strong&gt;Iran strikes on Amazon data centers caused permanent loss of customer data&lt;/strong&gt;&lt;/a&gt;: the cloud during war becomes foggy.&lt;/p&gt;

&lt;p&gt;📝 &lt;a href="https://www.phoronix.com/news/Intel-Bug-Bounty-Program-Ends" rel="noopener noreferrer"&gt;&lt;strong&gt;Intel Appears To End Its Bug Bounty Program&lt;/strong&gt;&lt;/a&gt;: if it's the case, why? It could be due to the amount of false-positive bugs found with LLMs, it can have a really huge impact on developers team. Curious to know more about the reason.&lt;/p&gt;




&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fz5sdcay7q0vggq6ha5fz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fz5sdcay7q0vggq6ha5fz.png" alt="Not quite my frequency" width="679" height="319"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fo00b41twz19n0lsxirpn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fo00b41twz19n0lsxirpn.png" alt="Chad third-party scraper" width="601" height="680"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fqsc3cnzi1xce1t1dhom6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fqsc3cnzi1xce1t1dhom6.png" alt=" " width="598" height="138"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fx17nww8qzebh1atl8aq5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fx17nww8qzebh1atl8aq5.png" alt="A matrix timeline" width="548" height="680"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ftku05s622omvkb1qrwkt.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ftku05s622omvkb1qrwkt.png" alt=" " width="659" height="680"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F99r7ybaxaowwl0vs7rd6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F99r7ybaxaowwl0vs7rd6.png" alt=" " width="679" height="445"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fi6t7o3vgkvlspf0na20n.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fi6t7o3vgkvlspf0na20n.png" alt=" " width="450" height="338"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fev23mukedrt55et7frdk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fev23mukedrt55et7frdk.png" alt=" " width="625" height="680"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F750ro2yq7ykmwiv0v6br.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F750ro2yq7ykmwiv0v6br.png" alt=" " width="680" height="550"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fx9s9gcza5e1uxk82w213.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fx9s9gcza5e1uxk82w213.png" alt=" " width="675" height="499"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F2d4zn69b5vmcsh50y5x2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F2d4zn69b5vmcsh50y5x2.png" alt=" " width="680" height="614"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;Cover Image by &lt;a href="https://unsplash.com/@sunira?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" rel="noopener noreferrer"&gt;Sunira Moses&lt;/a&gt; on &lt;a href="https://unsplash.com/photos/orange-and-green-pumpkins-on-blue-plastic-container-XZ83-3HJei0?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" rel="noopener noreferrer"&gt;Unsplash&lt;/a&gt;&lt;/p&gt;

</description>
      <category>weekly</category>
      <category>review</category>
    </item>
    <item>
      <title>Q&amp;D: Flutter App and Android-SDK</title>
      <dc:creator>Mathieu Kerjouan</dc:creator>
      <pubDate>Thu, 17 Sep 2026 08:00:00 +0000</pubDate>
      <link>https://dev.to/niamtokik/qd-flutter-app-and-android-sdk-2ncm</link>
      <guid>https://dev.to/niamtokik/qd-flutter-app-and-android-sdk-2ncm</guid>
      <description>&lt;p&gt;After having upgraded few tools on machine, one of my application was totally unable to run. I got a lot of warnings, especially this one:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;Warning: Flutter support for your project's Gradle version (8.14.0) will soon be dropped. Please upgrade your Gradle version to a version of at least 9.1.0 soon.                             
Alternatively, use the flag "--android-skip-build-dependency-validation" to bypass this check
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and finally...&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;FAILURE: Build failed with an exception.                                                                                                                                                      

* What went wrong:                                                                                                                                                                            
Execution failed for task ':app:compileFlutterBuildDebug'.                                                                                                                                    
&lt;/span&gt;&lt;span class="gp"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;A problem occurred starting process &lt;span class="s1"&gt;'command '&lt;/span&gt;/home/user/.local/share/mise/http-tarballs/dd5ae32abcea719e3c351c56a28308b91e2ce97fb5702bf2710c2527dde522af_strip_1/bin/flutter&lt;span class="s1"&gt;''&lt;/span&gt;             
&lt;span class="go"&gt;
* Try:                                                                                                                                                                                        
&lt;/span&gt;&lt;span class="gp"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;Run with &lt;span class="nt"&gt;--stacktrace&lt;/span&gt; option to get the stack trace.
&lt;span class="gp"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;Run with &lt;span class="nt"&gt;--info&lt;/span&gt; or &lt;span class="nt"&gt;--debug&lt;/span&gt; option to get more log output.
&lt;span class="gp"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;Run with &lt;span class="nt"&gt;--scan&lt;/span&gt; to get full insights.
&lt;span class="gp"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;Get more &lt;span class="nb"&gt;help &lt;/span&gt;at https://help.gradle.org.
&lt;span class="go"&gt;
BUILD FAILED in 1s
Running Gradle task 'assembleDebug'...                           1,270ms
Error: Gradle build failed due to Java/Gradle incompatibility.
The Java version used for the build is 25.0.3, which is incompatible with Gradle 8.14.
To fix this, you can either:
  1. Upgrade your project's Gradle version (typically in gradle-wrapper.properties to a version matching the range: compatible Gradle versions for Java 25.0.3 are 9.1.0 or newer).
&lt;/span&gt;&lt;span class="gp"&gt;  2. Use a different Java version for Flutter by running `flutter config --jdk-dir=&amp;lt;path&amp;gt;&lt;/span&gt;&lt;span class="sb"&gt;`&lt;/span&gt;&lt;span class="nb"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Annoying right? In fact, many other warnings were displayed, but what happened there? The last time, it was working without problem. Let have a look on the android sdk&lt;/p&gt;

&lt;h1&gt;
  
  
  &amp;nbsp;Android SDK Upgrade
&lt;/h1&gt;

&lt;p&gt;The "old" latest version of the android-sdk called &lt;a href="https://developer.android.com/studio/releases/past-releases/as-panda-4-release-notes" rel="noopener noreferrer"&gt;Panda 4&lt;/a&gt; was used, instead of the new latest version called &lt;a href="https://developer.android.com/studio/releases" rel="noopener noreferrer"&gt;Quail 4&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;cd &lt;/span&gt;Downloads
&lt;span class="go"&gt;
&lt;/span&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;wget https://edgedl.me.gvt1.com/android/studio/ide-zips/2026.1.4.7/android-studio-quail4-linux.tar.gz
&lt;span class="go"&gt;
&lt;/span&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;tar &lt;/span&gt;zxf android-studio-quail4-linux.tar.gz
&lt;span class="go"&gt;
&lt;/span&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;cd &lt;/span&gt;android-studio
&lt;span class="go"&gt;
&lt;/span&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;ls &lt;/span&gt;bin
&lt;span class="go"&gt;appletviewer.policy  game-tools.sh    lldb         studio              studio.svg
brokenPlugins.db     helpers          ltedit.sh    studio64.vmoptions
format.sh            idea.properties  profiler.sh  studio.png
fsnotifier           inspect.sh       restarter    studio.sh
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Android SDK Platforms and Tools Upgrade
&lt;/h1&gt;

&lt;p&gt;The latest android-studio version is now installed, but the SDK Platforms and the SDK Tools needs to be upgraded as well. It can be done via android studio directly in &lt;code&gt;Menu &amp;gt; Tools &amp;gt; SDK Managers&lt;/code&gt;. The versions to upgrade to should be displayed with the installed one as well. If needed, install some latest versions or missing tools.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;./bin/studio
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The upgraded versions should have been extracted in the &lt;code&gt;${HOME}/Android&lt;/code&gt; directory. It can also be done using the &lt;code&gt;sdkmanager&lt;/code&gt; tool.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;sdkmanager &lt;span class="nt"&gt;--update&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Flutter and Dart upgrade
&lt;/h1&gt;

&lt;p&gt;My development machine is using &lt;code&gt;mise&lt;/code&gt; to have the latest version of flutter and dart. The version of these applications are usually stored in the &lt;code&gt;.tool-versions&lt;/code&gt;. It can be upgraded using the &lt;code&gt;upgrade&lt;/code&gt; subcommand.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; ~/project
&lt;span class="go"&gt;
&lt;/span&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;cat&lt;/span&gt; .tool-versions
&lt;span class="go"&gt;flutter latest
dart latest

&lt;/span&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;mise upgrade
&lt;span class="c"&gt;...
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Environment Variables
&lt;/h1&gt;

&lt;p&gt;My environment was a mess, because many tools were living together and usually, because you want to do something quick, you put everything in your &lt;code&gt;~/.bashrc&lt;/code&gt;. Here the new conf.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# recreates a full clean path from scratch&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;PATH&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/bin:/usr/bin:/usr/local/bin
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;PATH&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/sbin:/usr/sbin:/usr/local/sbin:&lt;span class="nv"&gt;$PATH&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;PATH&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;HOME&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;/bin:&lt;span class="nv"&gt;$PATH&lt;/span&gt;

&lt;span class="c"&gt;# enable mise&lt;/span&gt;
&lt;span class="nb"&gt;eval&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;~/mise/bin/mise activate bash&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;

&lt;span class="c"&gt;# set android configuration&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;ANDROID_HOME&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;HOME&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;/Android/Sdk
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;PATH&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$ANDROID_HOME&lt;/span&gt;/tools:&lt;span class="nv"&gt;$PATH&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;PATH&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$ANDROID_HOME&lt;/span&gt;/tools/bin:&lt;span class="nv"&gt;$PATH&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;PATH&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$ANDROID_HOME&lt;/span&gt;/platform-tools:&lt;span class="nv"&gt;$PATH&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;PATH&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$ANDROID_HOME&lt;/span&gt;/cmake/4.1.2/bin:&lt;span class="nv"&gt;$PATH&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;PATH&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$ANDROID_HOME&lt;/span&gt;/cmdline-tools/latest/bin:&lt;span class="nv"&gt;$PATH&lt;/span&gt;

&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;CHROME_EXECUTABLE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;which chromium&lt;span class="si"&gt;)&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;EDITOR&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;vim
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Flutter and Gradle
&lt;/h1&gt;

&lt;p&gt;Gradle was crying because of an old version unsupported to some new versions installed. To be honest, my android application version is still quite simple, so, I fixed the issue by recreating the &lt;code&gt;android&lt;/code&gt; directory from the flutter project root.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; ~/project
&lt;span class="go"&gt;
&lt;/span&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;mv &lt;/span&gt;android android.old
&lt;span class="go"&gt;
&lt;/span&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;flutter create &lt;span class="nb"&gt;.&lt;/span&gt; &lt;span class="nt"&gt;--platforms&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;android
&lt;span class="go"&gt;Recreating project .... 
&lt;/span&gt;&lt;span class="c"&gt;...
&lt;/span&gt;&lt;span class="go"&gt;Resolving dependencies...                                                                                                                                                                     
Downloading packages...                                                                                                                                                                       
Got dependencies.                                                                                                                                                                             
Wrote 26 files.                                                                                                                                                                               

All done!                                                                                                                                                                                     
You can find general documentation for Flutter at: https://docs.flutter.dev/                                                                                                                  
Detailed API documentation is available at: https://api.flutter.dev/                                                                                                                          
If you prefer video documentation, consider: https://www.youtube.com/c/flutterdev                                                                                                             

In order to run your application, type:                                                                                                                                                       

&lt;/span&gt;&lt;span class="gp"&gt;  $&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;flutter run                                                                                                                                                                               
&lt;span class="go"&gt;
Your application code is in ./lib/main.dart.
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The application can now be restarted again.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;flutter run
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here the &lt;a href="https://docs.flutter.dev/reference/flutter-cli" rel="noopener noreferrer"&gt;&lt;code&gt;flutter&lt;/code&gt; command reference&lt;/a&gt;.&lt;/p&gt;

&lt;h1&gt;
  
  
  Another Gradle issue
&lt;/h1&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;WARNING: A restricted method in java.lang.System has been called                                                                                                                              
WARNING: java.lang.System::load has been called by net.rubygrapefruit.platform.internal.NativeLibraryLoader in an unnamed module (file:/home/user/.gradle/wrapper/dists/gradle-9.3.1-all/9ot9r
568e8zfvvd4mn8rbu1j0/gradle-9.3.1/lib/native-platform-0.22-milestone-29.jar)                                                                                                                  
WARNING: Use --enable-native-access=ALL-UNNAMED to avoid a warning for callers in this module                                                                                                 
WARNING: Restricted methods will be blocked in a future release unless native access is enabled 
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This one is a bit tricky. On the latest android-studio version, the bundled version of JDK is 25+. Let check that with &lt;code&gt;flutter doctor&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;flutter doctor &lt;span class="nt"&gt;--verbose&lt;/span&gt;
&lt;span class="c"&gt;...
&lt;/span&gt;&lt;span class="go"&gt;[✓] Android toolchain - develop for Android devices (Android SDK version 37.0.0) [248ms]                                                                                                      
    • Android SDK at /home/user/Android/Sdk                                                                                                                                                   
    • Emulator version 37.1.11.0 (build_id 15917651) (CL:N/A)                                                                                                                                 
    • Platform android-37.2, build-tools 37.0.0                                                                                                                                               
    • ANDROID_HOME = /home/user/Android/Sdk                                                                                                                                                   
    • Java binary at: /home/user/Downloads/android-studio/jbr/bin/java                                                                                                                        
      This is the JDK bundled with the latest Android Studio installation on this machine.                                                                                                    
      To manually set the JDK path, use: `flutter config --jdk-dir="path/to/jdk"`.                                                                                                            
    • Java version OpenJDK Runtime Environment (build 25.0.3+-15898627-b508.16)                                                                                                               
    • All Android licenses accepted.
&lt;/span&gt;&lt;span class="c"&gt;...
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Indeed, it looks like it uses OpenJDK25+... Just to confirm, let execute &lt;code&gt;java&lt;/code&gt; directly.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;~/Downloads/android-studio/jbr/bin/java &lt;span class="nt"&gt;-version&lt;/span&gt;
&lt;span class="go"&gt;openjdk version "25.0.3" 2026-04-21
OpenJDK Runtime Environment (build 25.0.3+-15898627-b508.16)
OpenJDK 64-Bit Server VM (build 25.0.3+-15898627-b508.16, mixed mode)
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It seems this version is not supported correctly with flutter applications, requiring JDK 21. To remove temporarily this warning message, instead of adding a flag, one can install an old version of the JDK from the system package manage for example.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;apt-get &lt;span class="nb"&gt;install &lt;/span&gt;openjdk-21-&lt;span class="o"&gt;{&lt;/span&gt;jre,jdk&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then, the project can be configured to use this one instead of the latest version available from the android studio.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;flutter config &lt;span class="nt"&gt;--jdk-dir&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/usr/lib/jvm/java-21-openjdk-amd64
&lt;span class="go"&gt;
&lt;/span&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;flutter doctor &lt;span class="nt"&gt;--verbose&lt;/span&gt;
&lt;span class="c"&gt;...
&lt;/span&gt;&lt;span class="go"&gt;[✓] Android toolchain - develop for Android devices (Android SDK version 37.0.0) [235ms]                                                                                                      
    • Android SDK at /home/user/Android/Sdk                                                                                                                                                   
    • Emulator version 37.1.11.0 (build_id 15917651) (CL:N/A)                                                                                                                                 
    • Platform android-37.2, build-tools 37.0.0                                                
    • ANDROID_HOME = /home/user/Android/Sdk                                                    
    • Java binary at: /usr/lib/jvm/java-21-openjdk-amd64/bin/java                                                                                                                             
      This JDK is specified in your Flutter configuration.                                                                                                                                    
      To change the current JDK, run: `flutter config --jdk-dir="path/to/jdk"`.                                                                                                               
    • Java version OpenJDK Runtime Environment (build 21.0.12.1+1-1-deb13u1-Debian)                                                                                                           
    • All Android licenses accepted.
&lt;/span&gt;&lt;span class="c"&gt;...
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Thanks to this &lt;a href="https://startdebugging.net/2026/08/fix-a-restricted-method-in-java-lang-system-has-been-called-in-a-flutter-gradle-build/" rel="noopener noreferrer"&gt;post&lt;/a&gt; from startdebugging.net, it helped me a lot to debug this issue.&lt;/p&gt;

&lt;h1&gt;
  
  
  Storage Issue
&lt;/h1&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;Failure [INSTALL_FAILED_INSUFFICIENT_STORAGE: Failed to override installation
location]
Error launching application on sdk gphone64 x86 64.
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It simply means the virtual machine used for android (the device used by flutter) is full and there is no enough free space available to install the application. This one is kinda easy to fix, in android-studio go to &lt;code&gt;Menu&lt;/code&gt; &amp;gt; &lt;code&gt;Tools&lt;/code&gt; &amp;gt; &lt;code&gt;Devices Manager&lt;/code&gt;, select the device to edit. In the &lt;code&gt;Additional settings&lt;/code&gt; tabs, below the &lt;code&gt;Storage&lt;/code&gt;&amp;nbsp;section, one can expand both the internal or global storage. Note: It will reset the data on the device.&lt;/p&gt;

&lt;h1&gt;
  
  
  Conclusion
&lt;/h1&gt;

&lt;p&gt;Modern programming is a huge pile of shit. Every time you do a small update/upgrade on one module or package, or on the core language to have the latest security patches, it breaks. That's annoying and explain why most of the applications are not safe. Developers don't really care about security, they wants to deliver quick. To do that, they will bypass all safety. Sadly, nothing changed during the last 10 or 20 years to build a mobile app easily. I've lost half a day to figure out what was the root cause... The good side? It's another confirmation about the whole ecosystem, it's a miracle everything is working correctly.&lt;/p&gt;

&lt;p&gt;As usual, hack it and try to have some fun!&lt;/p&gt;




&lt;p&gt;Cover Image by &lt;a href="https://unsplash.com/@tin1023565?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" rel="noopener noreferrer"&gt;Ticka Kao&lt;/a&gt; on &lt;a href="https://unsplash.com/photos/yellow-robot-toy-on-black-table-NGqWbKcjgJ4?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" rel="noopener noreferrer"&gt;Unsplash&lt;/a&gt;&lt;/p&gt;

</description>
      <category>flutter</category>
      <category>android</category>
      <category>tooling</category>
      <category>debugging</category>
    </item>
    <item>
      <title>Q&amp;D: PostgreSQL 18 on OpenBSD</title>
      <dc:creator>Mathieu Kerjouan</dc:creator>
      <pubDate>Tue, 15 Sep 2026 10:00:00 +0000</pubDate>
      <link>https://dev.to/niamtokik/qd-postgresql-18-on-openbsd-1hik</link>
      <guid>https://dev.to/niamtokik/qd-postgresql-18-on-openbsd-1hik</guid>
      <description>&lt;p&gt;If you need the latest version of PostgreSQL on OpenBSD, the &lt;a href="https://www.mail-archive.com/ports%40openbsd.org/msg137080.html" rel="noopener noreferrer"&gt;limits for the semaphores must be increased&lt;/a&gt;. Indeed, let imagine you want to deploy a fresh postgresql database (assuming the &lt;code&gt;/var/postgresql/data&lt;/code&gt; directory was not created or purged).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;doas pkg_add postgresql-server
&lt;span class="c"&gt;...
&lt;/span&gt;&lt;span class="go"&gt;
&lt;/span&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; /var/postgresql
&lt;span class="go"&gt;
&lt;/span&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;doas &lt;span class="nt"&gt;-u&lt;/span&gt; _postgresql initdb &lt;span class="nt"&gt;-D&lt;/span&gt; data
&lt;span class="go"&gt;The files belonging to this database system will be owned by user "_postgresql".                                                                              
This user must also own the server process.          

The database cluster will be initialized with locale "C".                     
The default database encoding has accordingly been set to "SQL_ASCII".         
The default text search configuration will be set to "english".               

Data page checksums are enabled.

fixing permissions on existing directory data ... ok
creating subdirectories ... ok                                                
selecting dynamic shared memory implementation ... posix
selecting default "max_connections" ... 20                           
selecting default "shared_buffers" ... 400kB                                  
selecting default time zone ... UTC
creating configuration files ... ok
running bootstrap script ... 2026-09-14 17:44:41.502 UTC [93045] FATAL:  could not create semaphores: No space left on device                                 
2026-09-14 17:44:41.502 UTC [93045] DETAIL:  Failed system call was semget(3810418, 17, 03600).                                                               
2026-09-14 17:44:41.502 UTC [93045] HINT:  This error does *not* mean that you have run out of disk space.  It occurs when either the system limit for the maximum number of semaphore sets (SEMMNI), or the system wide maximum number of semaphores (SEMMNS), would be exceeded.  You need to raise the respective kernel 
parameter.  Alternatively, reduce PostgreSQL's consumption of semaphores by reducing its "max_connections" parameter.                                         
        The PostgreSQL documentation contains more information about configuring your system for PostgreSQL.                                                  
child process exited with exit code 1                                          
initdb: removing contents of data directory "data"
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;An error! To fix it, &lt;code&gt;kern.seminfo.semmni&lt;/code&gt; and &lt;code&gt;kern.seminfo.semmns&lt;/code&gt; need to be modified.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;doas sysctl kern.seminfo.semmni&lt;span class="o"&gt;=&lt;/span&gt;256
&lt;span class="gp"&gt;kern.seminfo.semmni: 10 -&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;256
&lt;span class="go"&gt;
&lt;/span&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;doas sysctl kern.seminfo.semmns&lt;span class="o"&gt;=&lt;/span&gt;2048
&lt;span class="gp"&gt;kern.seminfo.semmns: 60 -&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;2048
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, the database can be initialized without issue.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;doas &lt;span class="nt"&gt;-u&lt;/span&gt; _postgresql initdb &lt;span class="nt"&gt;-D&lt;/span&gt; data                    
The files belonging to this database system will be owned by user &lt;span class="s2"&gt;"_postgresql"&lt;/span&gt;&lt;span class="nb"&gt;.&lt;/span&gt;                                                                             
This user must also own the server process.                                   

The database cluster will be initialized with locale &lt;span class="s2"&gt;"C"&lt;/span&gt;&lt;span class="nb"&gt;.&lt;/span&gt;                     
The default database encoding has accordingly been &lt;span class="nb"&gt;set &lt;/span&gt;to &lt;span class="s2"&gt;"SQL_ASCII"&lt;/span&gt;&lt;span class="nb"&gt;.&lt;/span&gt;        
The default text search configuration will be &lt;span class="nb"&gt;set &lt;/span&gt;to &lt;span class="s2"&gt;"english"&lt;/span&gt;&lt;span class="nb"&gt;.&lt;/span&gt;               

Data page checksums are enabled.       

fixing permissions on existing directory data ... ok                          
creating subdirectories ... ok         
selecting dynamic shared memory implementation ... posix                      
selecting default &lt;span class="s2"&gt;"max_connections"&lt;/span&gt; ... 100                                   
selecting default &lt;span class="s2"&gt;"shared_buffers"&lt;/span&gt; ... 128MB                                  
selecting default &lt;span class="nb"&gt;time &lt;/span&gt;zone ... UTC    
creating configuration files ... ok    
running bootstrap script ... ok        
performing post-bootstrap initialization ... ok                               
syncing data to disk ... ok            

initdb: warning: enabling &lt;span class="s2"&gt;"trust"&lt;/span&gt; authentication &lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="nb"&gt;local &lt;/span&gt;connections        
initdb: hint: You can change this by editing pg_hba.conf or using the option &lt;span class="nt"&gt;-A&lt;/span&gt;, or &lt;span class="nt"&gt;--auth-local&lt;/span&gt; and &lt;span class="nt"&gt;--auth-host&lt;/span&gt;, the next &lt;span class="nb"&gt;time &lt;/span&gt;you run initdb.              

Success. You can now start the database server using:                         

    pg_ctl &lt;span class="nt"&gt;-D&lt;/span&gt; data &lt;span class="nt"&gt;-l&lt;/span&gt; logfile start

&lt;span class="nv"&gt;$ &lt;/span&gt;doas rcctl start postgresql
postgresql&lt;span class="o"&gt;(&lt;/span&gt;ok&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It looks way better! The new configuration can now be added into &lt;code&gt;/etc/sysctl.conf&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"kern.seminfo.semmni=256"&lt;/span&gt; | doas &lt;span class="nb"&gt;tee&lt;/span&gt; &lt;span class="nt"&gt;-a&lt;/span&gt; /etc/sysctl.conf
&lt;span class="go"&gt;
&lt;/span&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"sysctl kern.seminfo.semmns=2048"&lt;/span&gt; | doas &lt;span class="nb"&gt;tee&lt;/span&gt; &lt;span class="nt"&gt;-a&lt;/span&gt; /etc/sysctl.conf
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The server should reboot with the good configuration now. You can configure your postgresql server now.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;doas &lt;span class="nt"&gt;-u&lt;/span&gt; _postgresql psql postgres
&lt;span class="go"&gt;psql (18.6)
Type "help" for help.

&lt;/span&gt;&lt;span class="gp"&gt;postgres=#&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Happy hacking and have fun!&lt;/p&gt;




&lt;p&gt;Cover Image by &lt;a href="https://unsplash.com/@d_seddon?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" rel="noopener noreferrer"&gt;Dan Seddon&lt;/a&gt; on &lt;a href="https://unsplash.com/photos/leopard-puffer-fish-TbgoCf4F3MM?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" rel="noopener noreferrer"&gt;Unsplash&lt;/a&gt;&lt;/p&gt;

</description>
      <category>openbsd</category>
      <category>postgres</category>
      <category>database</category>
      <category>systems</category>
    </item>
    <item>
      <title>WeekReview#202637</title>
      <dc:creator>Mathieu Kerjouan</dc:creator>
      <pubDate>Mon, 14 Sep 2026 08:00:00 +0000</pubDate>
      <link>https://dev.to/niamtokik/weekreview202637-2a56</link>
      <guid>https://dev.to/niamtokik/weekreview202637-2a56</guid>
      <description>&lt;p&gt;Paying for "cheap" virtual machines running my CI/CD pipelines is no fun. You will have the result quick, but you will not learn how to deploy this kind of infrastructure. As sysadmin, it's always nice to see how the tools used few years ago evolved... So, this week was about creating my own local privacy-first building infrastructure for Gitlab CI/CD. Based on the increasing cost of hosting providers due to the "AI revolution", hosting its own infrastructure can have a lot of benefit (and few drawbacks). What's the idea? &lt;/p&gt;

&lt;p&gt;To avoid information leaks like my own public address, the network will route all outgoing connections to a VPN or/and via a proxy. Each servers will be installed with an hardened version of Alpine Linux, and will have gitlab-runner enabled by default with a container manager (e.g. podman). Those servers are old laptops or cheap bare-metal devices (e.g. Intel NUCs, ARM boards). This infrastructure will also offer local isolated cache servers and a way to store artefacts.&lt;/p&gt;

&lt;p&gt;It was not really planned, but it's a nice idea to do that. In fact, I would like to also test this kind of infrastructure with &lt;code&gt;k3s&lt;/code&gt; to see if a kubernetes cluster can run in its own world, without a direct access to internet. Spoiler alert: it is already deployed on two workers, behind an OpenBSD firewall. It's a matter of time before a series of articles will be published here about that.&lt;/p&gt;

&lt;p&gt;This week was kinda busy, working on my application in Dart/Flutter, and most of the links are without comments because they have been barely read... Even more, dev.to is going to make me crazy. When a post is removed from a series, it is not displayed on user's profile. I created an &lt;a href="https://github.com/forem/forem/issues/23829#issuecomment-5630318665" rel="noopener noreferrer"&gt;issue&lt;/a&gt; hoping it will be fixed, but I was so angry about that, I started to work on my own post manager called &lt;a href="https://github.com/niamtokik/publish" rel="noopener noreferrer"&gt;&lt;code&gt;publish&lt;/code&gt;&lt;/a&gt; using only pandoc, Makefiles and shell scripting. I don't understand how a website like dev.to can be a "reference" for developers. Anyway, as usual, nothing is better than what you can do by yourself. A word on &lt;code&gt;publish&lt;/code&gt; project?&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;must be highly portable and run everywhere&lt;/li&gt;
&lt;li&gt;must be use simple markdown files&lt;/li&gt;
&lt;li&gt;must publish content in more than one format (e.g. html, pdf, epub, djvu...)&lt;/li&gt;
&lt;li&gt;must be easy to clone/export&lt;/li&gt;
&lt;li&gt;must be easy to backup&lt;/li&gt;
&lt;li&gt;must be easy to migrate&lt;/li&gt;
&lt;li&gt;must be flexible enough to deal with callbacks in any languages&lt;/li&gt;
&lt;li&gt;must generate good old files and directories&lt;/li&gt;
&lt;li&gt;must save its state as local files/directories as well&lt;/li&gt;
&lt;li&gt;all my publications will be firstly created there and then published on substack, medium and dev.to (and in other places as well if possible).&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;I'm really tired of migrating my content every 2 or 3 years, but I know think the best way is to keep everything open, and stay with your data locally.&lt;/p&gt;

&lt;h1&gt;
  
  
  Coding
&lt;/h1&gt;

&lt;p&gt;🏗️ &lt;a href="https://hex.pm/packages/snmpkit" rel="noopener noreferrer"&gt;&lt;strong&gt;snmpkit&lt;/strong&gt;&lt;/a&gt;: A comprehensive SNMP toolkit for Elixir featuring a unified API, pure Elixir implementation, and powerful device simulation.&lt;/p&gt;

&lt;p&gt;📝 &lt;a href="https://www.21verses.xyz/2026/09/04/Register_allocation_LLVM/" rel="noopener noreferrer"&gt;&lt;strong&gt;Register Allocation in the LLVM Backend&lt;/strong&gt;&lt;/a&gt;: an article on LLVM compiler optimization for registers allocation. In short, this is the algorithms used when the &lt;code&gt;-O&lt;/code&gt; flag is set. It's interesting to see register allocation is not a simple thing. This article focus on CPU though, GPU register allocation is a bit different.&lt;/p&gt;

&lt;p&gt;🏗️ &lt;a href="https://pub.dev/packages/listen" rel="noopener noreferrer"&gt;&lt;strong&gt;listen project&lt;/strong&gt;&lt;/a&gt;: A package to notify state changes to interested listeners in pure Dart.&lt;/p&gt;

&lt;p&gt;📝 &lt;a href="https://nand2mario.github.io/posts/2026/zsst-voodoo/" rel="noopener noreferrer"&gt;&lt;strong&gt;Recreating Voodoo Graphics and a Late-1990s Gaming PC on an FPGA&lt;/strong&gt;&lt;/a&gt;: another article about the z486 CPU, this time about recreating a graphic card using an FPGA.&lt;/p&gt;

&lt;p&gt;🏗️ &lt;a href="https://github.com/firecow/gitlab-ci-local" rel="noopener noreferrer"&gt;&lt;strong&gt;gitlab-ci-local project&lt;/strong&gt;&lt;/a&gt;: Run gitlab pipelines locally as shell executor or docker executor.&lt;/p&gt;

&lt;p&gt;🏗️ &lt;a href="https://github.com/vereis/ecto_middleware" rel="noopener noreferrer"&gt;&lt;strong&gt;ecto_middleware&lt;/strong&gt;&lt;/a&gt;: Implements the middleware pattern for your Ecto repos, a Plug-like concept for Ecto.&lt;/p&gt;

&lt;p&gt;📝 &lt;a href="https://uecker.codeberg.page/2026-09-05.html" rel="noopener noreferrer"&gt;&lt;strong&gt;Implementation of GCC's Nested Functions (vs. C++ Lambdas)&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;📑 &lt;a href="https://arxiv.org/abs/2504.02246" rel="noopener noreferrer"&gt;&lt;strong&gt;C*: Unifying Programming and Verification in C&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;🐦 &lt;a href="https://x.com/lemire/status/2098020509426294907" rel="noopener noreferrer"&gt;&lt;strong&gt;A quick overview of atomics in C&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;📑 &lt;a href="https://photonlibos.github.io/blog-20241014/Stackful_Coroutine_Made_Fast.pdf" rel="noopener noreferrer"&gt;&lt;strong&gt;Stackful Coroutine Made Fast&lt;/strong&gt;&lt;/a&gt;: from &lt;a href="https://photonlibos.github.io/" rel="noopener noreferrer"&gt;PhotonLibOS&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;📝 &lt;a href="https://david.alvarezrosa.com/posts/optimizing-a-spin-lock/" rel="noopener noreferrer"&gt;&lt;strong&gt;Optimizing a Spin-Lock&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;📝 &lt;a href="https://www.erlang-solutions.com/blog/how-to-write-a-phoenix-pubsub-adapter-tutorial-example-based-on-eventstore/" rel="noopener noreferrer"&gt;&lt;strong&gt;Implementing a Phoenix PubSub Adapter with EventStore&lt;/strong&gt;&lt;/a&gt;: a quick and short introduction to Phoenix &lt;a href="https://phoenix-pubsub.hexdocs.pm/Phoenix.PubSub.html" rel="noopener noreferrer"&gt;&lt;code&gt;PubSub&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;📝 &lt;a href="https://decompilation.education/" rel="noopener noreferrer"&gt;&lt;strong&gt;Decompilation Book&lt;/strong&gt;&lt;/a&gt;: A good introduction to decompilation (and reverse engineering).&lt;/p&gt;

&lt;h1&gt;
  
  
  System
&lt;/h1&gt;

&lt;p&gt;📝 &lt;a href="https://www.phoronix.com/news/Asahi-Linux-Official-M3" rel="noopener noreferrer"&gt;&lt;strong&gt;Asahi Linux Now Officially Supports Apple M3 Macs - With Caveats&lt;/strong&gt;&lt;/a&gt;: Linux on Apple M3 CPU will be great. Looking forward to have the same support on BSDs.&lt;/p&gt;

&lt;p&gt;📝 &lt;a href="https://www.rabbitmq.com/docs/compare/kafka" rel="noopener noreferrer"&gt;&lt;strong&gt;RabbitMQ vs. Apache Kafka&lt;/strong&gt;&lt;/a&gt;: it reminds me years ago when some of my colleagues were talking about comparing RabbitMQ and Kafka. This article is an up-to-date version of this discussion, with a nice conclusion: RabbitMQ is the better default. In general, both systems are now doing the same, with mostly the same performance. Anyway, a good summary every one working with queueing systems should read. A &lt;a href="https://ulearn-it.vercel.app/topics/rabbitmq-vs-kafka/study" rel="noopener noreferrer"&gt;study&lt;/a&gt; is also available.&lt;/p&gt;

&lt;p&gt;📝 &lt;a href="https://codon.org.uk/~mjg59/blog/p/systemio-conflicts-are-not-firmware-bugs/" rel="noopener noreferrer"&gt;&lt;strong&gt;SystemIO conflicts are not firmware bugs&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;🏗️ &lt;a href="https://github.com/ralsina/grafito" rel="noopener noreferrer"&gt;&lt;strong&gt;grafito project&lt;/strong&gt;&lt;/a&gt;: a simple, self-contained web-based log viewer for journalctl. It provides an intuitive interface to browse and filter system logs directly from your web browser.&lt;/p&gt;

&lt;p&gt;🏗️ &lt;a href="https://vinix-os.org/#about" rel="noopener noreferrer"&gt;&lt;strong&gt;Vinix OS&lt;/strong&gt;&lt;/a&gt;: Vinix initially is going to support every Apple Silicon Mac (only M1 Macs for now as of Sep 10 2026).&lt;/p&gt;

&lt;p&gt;📝 &lt;a href="https://eiln.github.io/posts/ane.html" rel="noopener noreferrer"&gt;&lt;strong&gt;Retrospectively Reverse-Engineering Apple's Neural Engine&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;📝 &lt;a href="https://web.archive.org/web/20201002094756/https://www.princeton.edu/~hos/mike/transcripts/thompson.htm" rel="noopener noreferrer"&gt;&lt;strong&gt;Interview with Ken Thompson, 9-6-89&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Network
&lt;/h1&gt;

&lt;p&gt;📑 &lt;a href="https://www.mdpi.com/2624-800X/6/2/72" rel="noopener noreferrer"&gt;&lt;strong&gt;De-Anonymization Techniques in the Tor Network Using an Experimental Testbed&lt;/strong&gt;&lt;/a&gt;: A really interesting publications doing a huge work on de-anonymizing tor network users using open-source tools, in an experimental network. In the end, nothing really new. It's well known if the user is not careful during browsing or when downloading something, it can  lead to information leaks. Whonix mostly fix this issue, even more when it is installed in QubeOS. Here the tools they used in this paper:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://github.com/shadow/shadow" rel="noopener noreferrer"&gt;shadow&lt;/a&gt;: Shadow is a discrete-event network simulator that directly executes real application code, enabling you to simulate distributed systems with thousands of network-connected processes in realistic and scalable private network experiments using your laptop, desktop, or server running Linux;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://gitlab.torproject.org/tpo/core/chutney" rel="noopener noreferrer"&gt;chutney&lt;/a&gt;: Tool for testing Tor network&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="//crysp.uwaterloo.ca/software/exptor/"&gt;ExperimenTor&lt;/a&gt;: A Testbed for Safe and Realistic Tor Experimentation &lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Database
&lt;/h1&gt;

&lt;p&gt;🏗️ &lt;a href="https://postgresql-anonymizer.readthedocs.io/en/latest/" rel="noopener noreferrer"&gt;&lt;strong&gt;PostgreSQL Anonymizer&lt;/strong&gt;&lt;/a&gt;: The main goal of this extension is to offer anonymization by design. We firmly believe that data masking rules should be written by the people who develop the application because they have the best knowledge of how the data model works. Therefore masking rules must be implemented directly inside the database schema. From &lt;a href="https://www.postgresql.org/about/news/postgresql-anonymizer-32-faster-pseudonymization-3373/" rel="noopener noreferrer"&gt;PostgreSQL News&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;🏗️ &lt;a href="https://github.com/labmiriade/pg_vault_tde" rel="noopener noreferrer"&gt;&lt;strong&gt;&lt;code&gt;pg_vault_tde&lt;/code&gt; project&lt;/strong&gt;&lt;/a&gt;: encrypts every tuple with AES-256-GCM at the Table Access Method layer. Data is encrypted before it reaches the storage manager and decrypted after it leaves. Encryption keys are managed by HashiCorp Vault / OpenBao or a local PKCS#12 wallet and cached in shared memory with automatic rotation. Seen from &lt;a href="https://www.postgresql.org/about/news/pg_vault_tde-v171-transparent-data-encryption-for-postgresql-17-and-18-3376/" rel="noopener noreferrer"&gt;postgresql news&lt;/a&gt;.&lt;/p&gt;

&lt;h1&gt;
  
  
  Storage
&lt;/h1&gt;

&lt;p&gt;🏗️ &lt;a href="https://github.com/deuxfleurs-org/garage" rel="noopener noreferrer"&gt;&lt;strong&gt;Garage project&lt;/strong&gt;&lt;/a&gt;: S3-compatible object store for small self-hosted geo-distributed deployments.&lt;/p&gt;

&lt;h1&gt;
  
  
  Security
&lt;/h1&gt;

&lt;p&gt;📝 &lt;a href="https://www.pikered.com/en/learn/bypass-remote-debugging-port-restrictions/" rel="noopener noreferrer"&gt;&lt;strong&gt;Activating Chrome DevTools Protocol in Memory: Bypassing –remote-debugging-port Restrictions&lt;/strong&gt;&lt;/a&gt;: shellcode injection on windows using Chrome Developer Tool.&lt;/p&gt;

&lt;p&gt;📝 &lt;a href="https://lina.sh/blog/hijacking-e164-arpa" rel="noopener noreferrer"&gt;&lt;strong&gt;I accidentally logged hundreds of thousands of phone calls to military bases&lt;/strong&gt;&lt;/a&gt;: a good story about hijacking &lt;code&gt;e164.arpa&lt;/code&gt; domains, a project created in the 2000's to associate phone number with DNS.&lt;/p&gt;

&lt;p&gt;📝 &lt;a href="https://calif.io/research/weworm" rel="noopener noreferrer"&gt;&lt;strong&gt;WeWorm, The first zero-click worm to spread through WeChat calls across iOS and Android.&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;▶️ &lt;a href="https://www.youtube.com/watch?v=y8Kagu3r3Z4" rel="noopener noreferrer"&gt;&lt;strong&gt;Deanonymizing Monero Transactions in Tor Network&lt;/strong&gt;&lt;/a&gt;: an introduction to deanonymizing monero transactions, but it has been fixed in the latest versions (quick). btw, I liked the fake VPN ads but I also liked the truth behind the private VPN companies giving logs to goverments.&lt;/p&gt;

&lt;p&gt;▶️ &lt;a href="https://www.youtube.com/watch?v=3wlNemFwbwE" rel="noopener noreferrer"&gt;&lt;strong&gt;The Tor Project Just Gaslit Their Entire User Base&lt;/strong&gt;&lt;/a&gt;: another project lying to their users. Tor browser does not protect against OS fingerprint, that's a shame, but the worst part is... they are saying the opposite in their communication. Don't trust anyone, again.&lt;/p&gt;

&lt;p&gt;📝 &lt;a href="https://blog.quarkslab.com/from-p-code-to-gnn-extract-binary-code-semantics.html" rel="noopener noreferrer"&gt;&lt;strong&gt;From P-Code to GNN: extract binary code semantics&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;📝 &lt;a href="https://www.praetorian.com/blog/ble-testing-caeruleus/" rel="noopener noreferrer"&gt;&lt;strong&gt;Bluetooth Low Energy Security Testing, Consolidated: Introducing Caeruleus&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Security/Cryptography
&lt;/h1&gt;

&lt;p&gt;📝 &lt;a href="https://pbxscience.com/engineer-factors-rsa-260-ending-a-35-year-cryptographic-challenge/" rel="noopener noreferrer"&gt;&lt;strong&gt;Engineer Factors RSA-260, Ending a 35-Year Cryptographic Challenge&lt;/strong&gt;&lt;/a&gt;: lot of noise here, but RSA-260 (260 bits RSA keys) have been broken. At least... One of them.&lt;/p&gt;

&lt;p&gt;📑 &lt;a href="https://arxiv.org/abs/2609.05625" rel="noopener noreferrer"&gt;&lt;strong&gt;Computing 256-bit elliptic curve discrete logarithms in 26 days on a fault-tolerant trapped-ion quantum computer with 20,000 qubits&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Security/OSINT
&lt;/h1&gt;

&lt;p&gt;🏗️ &lt;a href="https://github.com/0x6rss/instagram-private-graph" rel="noopener noreferrer"&gt;&lt;strong&gt;Instagram OSINT Relationship Analysis project&lt;/strong&gt;&lt;/a&gt;: Analyze the followers and following accounts that a private (hidden) Instagram account interacts with.&lt;/p&gt;

&lt;h1&gt;
  
  
  Security/BlueTeam
&lt;/h1&gt;

&lt;p&gt;📝 &lt;a href="https://medium.com/@costin.raiu/mikrotik-ssh-0day-exploitation-in-the-wild-20da4587d9b2" rel="noopener noreferrer"&gt;&lt;strong&gt;MikroTik ssh 0day exploitation in the wild&lt;/strong&gt;&lt;/a&gt;: a short story about a 0 day exploited on Mikrotik  routers via SSH.&lt;/p&gt;

&lt;h1&gt;
  
  
  Security/RedTeam
&lt;/h1&gt;

&lt;p&gt;📝 &lt;a href="https://hetmehta.com/posts/powershell-for-hackers/" rel="noopener noreferrer"&gt;&lt;strong&gt;PowerShell for Hackers: Exploitation Essentials&lt;/strong&gt;&lt;/a&gt;: not a big fan of powershell, but it's a good introduction for penetration testing.&lt;/p&gt;

&lt;p&gt;🏗️ &lt;a href="https://github.com/NazaninNazari/XSS_Labs" rel="noopener noreferrer"&gt;&lt;strong&gt;XSS Labs project&lt;/strong&gt;&lt;/a&gt;: Hands-on XSS labs for learning, practicing, and understanding Cross-Site Scripting vulnerabilities.&lt;/p&gt;

&lt;h1&gt;
  
  
  Embedded
&lt;/h1&gt;

&lt;p&gt;📝 &lt;a href="https://www.digikey.com/en/blog/scheme-it-schematic-drawing?article_name=scheme-it:_schematic_draw" rel="noopener noreferrer"&gt;&lt;strong&gt;Scheme-it: Schematic Drawing, Flow and Block Diagramming Made Easy&lt;/strong&gt;&lt;/a&gt;: a quick introduction to scheme-it to create and design electronic schema. Those schema can then be imported in KiCAD.&lt;/p&gt;

&lt;p&gt;📝 &lt;a href="https://www.digikey.com/en/maker/blogs/2024/deep-dive-into-pcb-manufacturing-techniques-milling" rel="noopener noreferrer"&gt;&lt;strong&gt;Deep Dive Into PCB Manufacturing Techniques: Milling&lt;/strong&gt;&lt;/a&gt;: a short post on PCB milling.&lt;/p&gt;

&lt;p&gt;📝 &lt;a href="https://www.digikey.com/en/maker/projects/esp32-audio-project-part-i-internet-radio-with-is-dac/b8378782c8524ab78bc1335a2ddb57cb" rel="noopener noreferrer"&gt;&lt;strong&gt;ESP32 Audio Project - Part I: Internet Radio with I²S DAC&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;📝 &lt;a href="https://www.mobile-hacker.com/2026/09/07/chameleon-ultra-guide-to-rfid-reading-emulation-and-testing/" rel="noopener noreferrer"&gt;&lt;strong&gt;Chameleon Ultra: Guide to RFID Reading, Emulation and Testing&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;🏗️ &lt;a href="https://www.crowdsupply.com/htwave/integrive-100" rel="noopener noreferrer"&gt;&lt;strong&gt;A standalone, real-time 2x2 MIMO software-defined radio (SDR) platform for advanced wireless research and rapid prototyping&lt;/strong&gt;&lt;/a&gt;: a standalone, real-time 2x2 MIMO software-defined radio (SDR) platform for advanced wireless research and rapid prototyping. With FPGA-accelerated wireless processing, ultra-low phase noise design, and a proven real-time PHY baseline.&lt;/p&gt;

&lt;h1&gt;
  
  
  Update/Upgrade
&lt;/h1&gt;

&lt;p&gt;🔄 &lt;a href="https://blog.netbsd.org/tnf/entry/netbsd_9_5_released_and" rel="noopener noreferrer"&gt;&lt;strong&gt;NetBSD 9.5&lt;/strong&gt;&lt;/a&gt;: NetBSD 9.5, the fifth (and final) release from the NetBSD 9 stable branch, end-of-support for all NetBSD-9.x. The full announcement can be found on &lt;a href="https://netbsd.org/releases/formal-9/NetBSD-9.5.html" rel="noopener noreferrer"&gt;the release page&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;🔄 &lt;a href="https://ninenines.eu/articles/cowboy-2.19.0/" rel="noopener noreferrer"&gt;&lt;strong&gt;Cowboy 2.19, Cowlib 2.20, Gun 2.6, Ranch 2.3&lt;/strong&gt;&lt;/a&gt;: this is an important release for all the cowboy-suite libraries. Cowboy is now only support OTP-27+ and will drop support for all versions of Erlang without security patches. The release on Github: &lt;a href="https://github.com/ninenines/cowlib/releases/tag/2.20.0" rel="noopener noreferrer"&gt;cowlib-2.20.0&lt;/a&gt;, &lt;a href="https://github.com/ninenines/ranch/releases/tag/2.3.0" rel="noopener noreferrer"&gt;ranch-2.3.0&lt;/a&gt;,  &lt;a href="https://github.com/ninenines/cowboy/releases/tag/2.19.0" rel="noopener noreferrer"&gt;cowboy-2.19.0&lt;/a&gt; and &lt;a href="https://github.com/ninenines/gun/releases/tag/2.6.0" rel="noopener noreferrer"&gt;gun-2.6.0&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;🔄 &lt;a href="https://github.com/novaframework/nova/releases/tag/v0.17.0" rel="noopener noreferrer"&gt;&lt;strong&gt;Nova 0.17.0&lt;/strong&gt;&lt;/a&gt;: optimization update.&lt;/p&gt;

&lt;p&gt;🔄 &lt;a href="https://github.com/novaframework/nova/releases/tag/v0.18.0" rel="noopener noreferrer"&gt;&lt;strong&gt;Nova 0.18.0&lt;/strong&gt;&lt;/a&gt;: another update.&lt;/p&gt;

&lt;p&gt;🔄 &lt;a href="https://www.openbsd.org/errata79.html" rel="noopener noreferrer"&gt;&lt;strong&gt;OpenBSD 7.9 syspatch security upgrade&lt;/strong&gt;&lt;/a&gt;: a lot of patches, impacting opensmtpd, nfs, wscons, shmat, libexpat, X and ldapd.&lt;/p&gt;

&lt;h1&gt;
  
  
  Providers
&lt;/h1&gt;

&lt;p&gt;🌐 &lt;a href="https://bullionet.com" rel="noopener noreferrer"&gt;&lt;strong&gt;Bullionet&lt;/strong&gt;&lt;/a&gt;:  cheap bare-metal server in France (Paris, Marseilles, Lille). Announced on &lt;a href="https://x.com/oliviermis/status/2096506930931913060?s=20" rel="noopener noreferrer"&gt;X/Twitter&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;🌐 &lt;a href="https://www.netcup.com" rel="noopener noreferrer"&gt;&lt;strong&gt;netcup&lt;/strong&gt;&lt;/a&gt;: low cost virtual servers, and interesting &lt;a href="https://www.netcup.com/en/deals" rel="noopener noreferrer"&gt;deals&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;🌐 &lt;a href="https://contabo.com/en-us/" rel="noopener noreferrer"&gt;&lt;strong&gt;contabo&lt;/strong&gt;&lt;/a&gt;: low cost &lt;a href="https://contabo.com/en/vps/" rel="noopener noreferrer"&gt;virtual servers&lt;/a&gt;, pretty expensive &lt;a href="https://contabo.com/en/dedicated-servers/" rel="noopener noreferrer"&gt;bare metal&lt;/a&gt; ones though.&lt;/p&gt;

&lt;p&gt;🌐 &lt;a href="https://my.speedypage.com/store" rel="noopener noreferrer"&gt;&lt;strong&gt;speedypage&lt;/strong&gt;&lt;/a&gt;: in pound (uk), quite expensive bare metal servers, but the price for virtual servers looks great.&lt;/p&gt;

&lt;p&gt;🌐 &lt;a href="https://euronodes.com" rel="noopener noreferrer"&gt;&lt;strong&gt;euronodes&lt;/strong&gt;&lt;/a&gt;: virtual machines are cheap (&amp;lt;5€), bare-metal servers are expensive. Data centers in Europe (germany, portugal, spain and czech republic).&lt;/p&gt;

&lt;p&gt;🌐 &lt;a href="https://macserve.io" rel="noopener noreferrer"&gt;&lt;strong&gt;macserve&lt;/strong&gt;&lt;/a&gt;: is it a joke?&lt;/p&gt;

&lt;p&gt;🌐 &lt;a href="https://boxedtux.com/" rel="noopener noreferrer"&gt;&lt;strong&gt;BoxedTux&lt;/strong&gt;&lt;/a&gt;: Deploy a full Linux virtual server in under 90 seconds. Root access, public IP, your choice of distro — no credit card, no vendor lock-in.&lt;/p&gt;

&lt;p&gt;🌐 &lt;a href="https://boxybsd.com/" rel="noopener noreferrer"&gt;&lt;strong&gt;BoxyBSD&lt;/strong&gt;&lt;/a&gt;: BoxyBSD offers free VPS instances for exploring FreeBSD, OpenBSD, NetBSD and many other BSD or Solaris based systems. Get hands-on experience, experiment safely, and join a growing community of BSD enthusiasts.&lt;/p&gt;

&lt;h1&gt;
  
  
  Misc
&lt;/h1&gt;

&lt;p&gt;🌐 &lt;a href="https://www.mini-itx.com" rel="noopener noreferrer"&gt;&lt;strong&gt;Mini ITX Shop&lt;/strong&gt;&lt;/a&gt;: A good place to find small-sized computers/boards.&lt;/p&gt;

&lt;p&gt;🌐 &lt;a href="https://www.mhzshop.com/" rel="noopener noreferrer"&gt;&lt;strong&gt;Mhz Shop&lt;/strong&gt;&lt;/a&gt;: A good place to find wireless hardware and devices.&lt;/p&gt;

&lt;p&gt;📝 &lt;a href="https://www.zerohedge.com/markets/oklahoma-bitcoin-mining-site-condemned-after-major-water-leak" rel="noopener noreferrer"&gt;&lt;strong&gt;Under-The-Radar Oklahoma Bitcoin Mining Site Condemned After Leaking 3 Million Gallons Of Water&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;🏗️ &lt;a href="https://github.com/osfv/BraveDebloater" rel="noopener noreferrer"&gt;&lt;strong&gt;BraveDebloater project&lt;/strong&gt;&lt;/a&gt;: Safety-first Windows PowerShell debloater for Brave Browser using enterprise policies, dry-run mode, backups, and restore.&lt;/p&gt;

&lt;p&gt;📝 &lt;a href="https://hackersarise.thinkific.com/courses/private-cellular-network" rel="noopener noreferrer"&gt;&lt;strong&gt;Build Your Own Private Cellular Network&lt;/strong&gt;&lt;/a&gt;: kinda expensive ($999) but looks interesting.&lt;/p&gt;

&lt;p&gt;🏗️ &lt;a href="https://nobaraproject.org/index.html" rel="noopener noreferrer"&gt;&lt;strong&gt;Nobora Project&lt;/strong&gt;&lt;/a&gt;:  A Fedora-based desktop, tuned for gaming, streaming, and content creation — so you can skip the tweaking and start doing. &lt;/p&gt;

&lt;p&gt;📟 &lt;a href="https://sipeed.com/nanokvm-go" rel="noopener noreferrer"&gt;&lt;strong&gt;Sipeed NanoKVM-Go&lt;/strong&gt;&lt;/a&gt;: an updated version of the NanoKVM, perfect for remote control and debugging a system remotely.&lt;/p&gt;

&lt;p&gt;🐦 &lt;a href="https://x.com/BetterCallMedhi/status/2097472336257863722?s=20" rel="noopener noreferrer"&gt;&lt;strong&gt;go fuck yourself @sama&lt;/strong&gt;&lt;/a&gt;: a reaction regarding the last "discovery" made by anthropic in the mathematical field. Below the most interesting part to me. Your data, your ideas, or your researches are not safely protected by those companies.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;to this theoretical imposture you add a disgusting ethical and industrial cynicism &lt;strong&gt;taking advantage of private codex sessions and informal preprints from academic researchers to siphon their research leads and then trying to redact or erase the contribution of levent alpöge&lt;/strong&gt; under the pretext that he works at rival anthropic is intellectual serfdom openai behaves like a feudal lord of silicon appropriating the cognitive subsistence of independent scholars threatening their careers behind closed doors if they protest and turning community academic labor into a privatized pressrelease [...] real science is not a clout chase on social media or a compute spike spent to rob the clay mathematics institute it is a quest for elegance physical truth and universal rigor to decode reality [...] the most dangerous aspect of this maneuver is not the mathematical exaggeration but the corporate enclosure of scientific discovery by keeping these frontier systems locked behind outcome based pricing licensing barriers &amp;amp; proprietary API walls [...] when mathematical reality itself gets reduced to synthetic token production swallowed by closed infrastructure we transition from open academic inquiry to technological feudalism&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;🌐 &lt;a href="https://www.blackhatworld.com" rel="noopener noreferrer"&gt;&lt;strong&gt;Black Hat World Forum&lt;/strong&gt;&lt;/a&gt;: discovering this forum recently, about SEO.&lt;/p&gt;




&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fzvhuuh5vxzgdihlyzz8d.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fzvhuuh5vxzgdihlyzz8d.png" alt=" " width="544" height="680"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F96ipp65da3qd4qcdkitr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F96ipp65da3qd4qcdkitr.png" alt=" " width="476" height="680"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ffpu9t1mw5b3x1533i1bk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ffpu9t1mw5b3x1533i1bk.png" alt=" " width="500" height="676"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Flprbhse3ivqw9u4jiogj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Flprbhse3ivqw9u4jiogj.png" alt=" " width="679" height="382"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fmbjztqy66apca8t8c9ai.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fmbjztqy66apca8t8c9ai.png" alt=" " width="680" height="680"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fdjy4yh4i9ochqiojaj7b.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fdjy4yh4i9ochqiojaj7b.png" alt=" " width="669" height="680"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fwzk304rcfwvy8d5ljb01.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fwzk304rcfwvy8d5ljb01.png" alt=" " width="457" height="680"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F97kef6gmftjlbkrbwotv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F97kef6gmftjlbkrbwotv.png" alt=" " width="640" height="560"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fx6gdlgzabo1b5zok5d7a.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fx6gdlgzabo1b5zok5d7a.png" alt=" " width="511" height="640"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F0c839tekgd7bhj7b0ymm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F0c839tekgd7bhj7b0ymm.png" alt=" " width="443" height="680"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F33f8uufwjtkj1o5cqggg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F33f8uufwjtkj1o5cqggg.png" alt=" " width="680" height="680"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fm4ymke1h5i34zf3fyr79.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fm4ymke1h5i34zf3fyr79.png" alt=" " width="460" height="587"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fye2o9oakewcb9ipjt100.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fye2o9oakewcb9ipjt100.png" alt=" " width="552" height="519"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fv0chaohj280r2l8bzwef.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fv0chaohj280r2l8bzwef.png" alt=" " width="567" height="680"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;Cover Image by &lt;a href="https://unsplash.com/@artem_kniaz?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" rel="noopener noreferrer"&gt;Artem Kniaz&lt;/a&gt; on &lt;a href="https://unsplash.com/photos/brown-wooden-boat-on-body-of-water-during-daytime-e3K4OOI3DcI?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" rel="noopener noreferrer"&gt;Unsplash&lt;/a&gt;&lt;/p&gt;

</description>
      <category>review</category>
      <category>weekly</category>
      <category>notes</category>
      <category>documentation</category>
    </item>
    <item>
      <title>Q&amp;D: Dart on Alpine Linux</title>
      <dc:creator>Mathieu Kerjouan</dc:creator>
      <pubDate>Thu, 10 Sep 2026 10:00:00 +0000</pubDate>
      <link>https://dev.to/niamtokik/qd-dart-on-alpine-linux-33n7</link>
      <guid>https://dev.to/niamtokik/qd-dart-on-alpine-linux-33n7</guid>
      <description>&lt;p&gt;Running Dart outside of the main distribution can be challenging. In fact, my first idea was to compile it from sources, but it seems most of the projects are simply using the binaries from Google instead of building the sources directly from the official Dart repository. That's a shame from an "open-source" language but anyway... Here some methods to use Dart on Alpine Linux.&lt;/p&gt;

&lt;h1&gt;
  
  
  Using a Container
&lt;/h1&gt;

&lt;p&gt;The Dart Team offers a &lt;a href="https://hub.docker.com/_/dart" rel="noopener noreferrer"&gt;Docker image&lt;/a&gt; with the latest version of Dart from the Google Dart binaries. This is probably the easiest way to use Dart on Alpine Linux without adding a lot of useless dependencies in your system.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;#&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;podman run &lt;span class="nt"&gt;-it&lt;/span&gt; dart sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;See also:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://github.com/dart-lang/dart-docker" rel="noopener noreferrer"&gt;Official Dart Docker Image source code&lt;/a&gt;;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://hub.docker.com/_/dart" rel="noopener noreferrer"&gt;Official Dart Docker Image&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Using &lt;code&gt;asdf&lt;/code&gt; or &lt;code&gt;mise&lt;/code&gt;
&lt;/h1&gt;

&lt;p&gt;&lt;code&gt;asdf&lt;/code&gt; and &lt;code&gt;mise&lt;/code&gt; can be used to bootstrap your systems. As usual, the Dart binaries are from Google.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;#&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;asdf plugin add dart
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;See also:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://asdf-vm.com/manage/plugins.html" rel="noopener noreferrer"&gt;asdf plugins&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://github.com/PatOConnor43/asdf-dart" rel="noopener noreferrer"&gt;asdf dart plugin&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Using Google Binaries
&lt;/h1&gt;

&lt;p&gt;Then, why not downloading ourselves the binaries from Google and installing it on Alpine Linux directly. It will require "only" &lt;code&gt;gcompat&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;#&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;apk update
&lt;span class="go"&gt;
&lt;/span&gt;&lt;span class="gp"&gt;#&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;apk add curl gcompat
&lt;span class="go"&gt;
&lt;/span&gt;&lt;span class="gp"&gt;#&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;curl &lt;span class="nt"&gt;-Lo&lt;/span&gt; dartsdk-linux-x64-release.zip https://storage.googleapis.com/dart-archive/channels/stable/release/3.13.3/sdk/dartsdk-linux-x64-release.zip
&lt;span class="go"&gt;
&lt;/span&gt;&lt;span class="gp"&gt;#&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;unzip dartsdk-linux-x64-release.zip
&lt;span class="go"&gt;
&lt;/span&gt;&lt;span class="gp"&gt;#&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;cd &lt;/span&gt;dart-sdk
&lt;span class="go"&gt;
&lt;/span&gt;&lt;span class="gp"&gt;#&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;./bin/dart &lt;span class="nt"&gt;--version&lt;/span&gt;
&lt;span class="go"&gt;Dart SDK version: 3.13.3 (stable) (Tue Sep 1 01:07:17 2026 -0700) on "linux_x64"

&lt;/span&gt;&lt;span class="gp"&gt;#&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;PATH&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;PATH&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;:&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;pwd&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;/bin
&lt;span class="go"&gt;
&lt;/span&gt;&lt;span class="gp"&gt;#&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;dart create t &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;cd &lt;/span&gt;t
&lt;span class="go"&gt;
&lt;/span&gt;&lt;span class="gp"&gt;#&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;dart run
&lt;span class="go"&gt;Building package executable... 
Built t:t.
Hello world: 42!
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The binaries are running on Alpine Linux, but we should be careful, they have been made on Debian-like system (trixie). For example, &lt;code&gt;ldd&lt;/code&gt; is not really happy due to &lt;code&gt;__cxa_thread_atexit_impl&lt;/code&gt; missing symbol.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;#&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;ldd dart
&lt;span class="go"&gt;        /lib64/ld-linux-x86-64.so.2 (0x7925aad9e000)
&lt;/span&gt;&lt;span class="gp"&gt;        libdl.so.2 =&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;/lib64/ld-linux-x86-64.so.2 &lt;span class="o"&gt;(&lt;/span&gt;0x7925aad9e000&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="gp"&gt;        libpthread.so.0 =&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;/lib64/ld-linux-x86-64.so.2 &lt;span class="o"&gt;(&lt;/span&gt;0x7925aad9e000&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="gp"&gt;        libm.so.6 =&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;/lib64/ld-linux-x86-64.so.2 &lt;span class="o"&gt;(&lt;/span&gt;0x7925aad9e000&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="gp"&gt;        libc.so.6 =&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;/lib64/ld-linux-x86-64.so.2 &lt;span class="o"&gt;(&lt;/span&gt;0x7925aad9e000&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="gp"&gt;        ld-linux-x86-64.so.2 =&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;/lib/ld-linux-x86-64.so.2 &lt;span class="o"&gt;(&lt;/span&gt;0x7925aa81f000&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="go"&gt;Error relocating dartaotruntime: __cxa_thread_atexit_impl: symbol not found
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;See also:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://dart.dev/get-dart/archive#stable-channel" rel="noopener noreferrer"&gt;Dart SDK archive Stable channel&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Compiling From Sources
&lt;/h1&gt;

&lt;p&gt;What a mess. I thought it would have been easy to compile Dart from sources, but it's not the case, especially on Alpine Linux. I started to work on it, but it's not ready yet, mostly due to the &lt;a href="https://chromium.googlesource.com/chromium/tools/depot_tools.git" rel="noopener noreferrer"&gt;google tools&lt;/a&gt; required for the compilation, producing a shit-ton of errors. Anyway, here a quick list of the dependencies&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;#&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;apk update
&lt;span class="go"&gt;
&lt;/span&gt;&lt;span class="gp"&gt;#&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;apk add git python3 curl xz gn clang make py3-virtualenv py3-setuptools py3-pip bash
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;See also:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://github.com/dart-lang/sdk/issues/36018" rel="noopener noreferrer"&gt;Building dart sdk&lt;/a&gt; on Github issues&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Conclusion
&lt;/h1&gt;

&lt;p&gt;I need a recent version of Dart, Flutter and Android SDK in a container. Unfortunately, the only ones have found are old, unmaintained or unofficial (it means trusting people I don't know).&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://github.com/MobileDevOps/android-sdk-image" rel="noopener noreferrer"&gt;Docker image for Android SDK&lt;/a&gt;: a docker image with the latest android sdk ONLY (no dart, no flutter);&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://github.com/thyrlian/AndroidSDK" rel="noopener noreferrer"&gt;AndroidSDK&lt;/a&gt;: another docker image containing the latest android SDK;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://github.com/davils-com/kosmos" rel="noopener noreferrer"&gt;Kosmos&lt;/a&gt;: another docker image with android SDK;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://dev.todocker-android-sdk"&gt;docker-android-sdk&lt;/a&gt;: again, another docker image with android SDK;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://github.com/mingchen/docker-android-build-box" rel="noopener noreferrer"&gt;Docker Android Build Box&lt;/a&gt;: docker image containing android SDK, JDK, and Flutter. This is the closed ones, but it is huge (5.5GB). I would like to avoid fetching the whole universe;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://github.com/its-me/image.flutter" rel="noopener noreferrer"&gt;image.flutter&lt;/a&gt;: a docker image containing flutter and the android sdk. Perhaps the good catch, but it uses an old version of flutter, and not even sure it works correctly (I like the &lt;code&gt;localhost/android-sdk&lt;/code&gt; source image). To be tested.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Anyway, building and releasing mobile application is a PITA. I understand why so many companies are selling a full build effortless pipeline, that's business.&lt;/p&gt;

&lt;p&gt;As usual, have fun and happy hacking!&lt;/p&gt;




&lt;p&gt;Cover Image by &lt;a href="https://unsplash.com/@camila_mof?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" rel="noopener noreferrer"&gt;Camila Mofsovich&lt;/a&gt; on &lt;a href="https://unsplash.com/photos/darts-drinks-and-jars-on-a-table-KyjXWDV6TIA?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" rel="noopener noreferrer"&gt;Unsplash&lt;/a&gt;&lt;/p&gt;

</description>
      <category>dart</category>
      <category>alpinelinux</category>
      <category>alpine</category>
      <category>sysadmin</category>
    </item>
  </channel>
</rss>
