<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="4.3.2">Jekyll</generator><link href="https://ohmycloud.github.io/feed.xml" rel="self" type="application/atom+xml" /><link href="https://ohmycloud.github.io/" rel="alternate" type="text/html" /><updated>2025-05-08T14:18:37+00:00</updated><id>https://ohmycloud.github.io/feed.xml</id><title type="html">焉知非鱼</title><subtitle>Just another programming blog</subtitle><author><name>ohmycloud</name></author><entry><title type="html">Happy 37th Birthday</title><link href="https://ohmycloud.github.io/2025/05/07/happy-37th-birthday.html" rel="alternate" type="text/html" title="Happy 37th Birthday" /><published>2025-05-07T00:00:00+00:00</published><updated>2025-05-07T00:00:00+00:00</updated><id>https://ohmycloud.github.io/2025/05/07/happy-37th-birthday</id><content type="html" xml:base="https://ohmycloud.github.io/2025/05/07/happy-37th-birthday.html"><![CDATA[<div class="dialog cop" title="Cop">
          <div class="dialog-head" aria-hidden="true">
          <?xml version="1.0" ?>
<!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
<svg width="800px" height="800px" viewBox="0 0 300 300" id="giraffe" version="1.1" xml:space="preserve" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g>
<path d="   M62,61.867h60v28H88.013c-7.739,0-16.47-5.734-19.521-12.853L62,61.867z" style="fill-rule:evenodd;clip-rule:evenodd;fill:#FFDD95;stroke:#000000;stroke-width:8;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;"/>
<path d="   M246,61.867h-60v28h33.987c7.739,0,16.47-5.734,19.521-12.853L246,61.867z" style="fill-rule:evenodd;clip-rule:evenodd;fill:#FFDD95;stroke:#000000;stroke-width:8;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;"/>
<path d="   M130,39.895c0-5.539,4.439-10.028,10-10.028c5.523,0,10,4.487,10,10.028v25.972h-20V39.895z" style="fill-rule:evenodd;clip-rule:evenodd;fill:#DDDDDD;stroke:#000000;stroke-width:7.7333;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;"/>
<path d="   M162,39.895c0-5.539,4.439-10.028,10-10.028c5.523,0,10,4.487,10,10.028v25.972h-20V39.895z" style="fill-rule:evenodd;clip-rule:evenodd;fill:#DDDDDD;stroke:#000000;stroke-width:7.7333;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;"/>
<path d="   M120.793,277.867h66.413l22.63-192.163c1.55-13.165-8.069-23.837-21.495-23.837h-68.684c-13.422,0-23.04,10.712-21.495,23.837   L120.793,277.867z" style="fill-rule:evenodd;clip-rule:evenodd;fill:#FBAD4A;stroke:#000000;stroke-width:8;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;"/>
<ellipse cx="154" cy="213.867" rx="64" ry="32" style="fill-rule:evenodd;clip-rule:evenodd;fill:#FFDD95;stroke:#000000;stroke-width:8;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;"/>
<ellipse cx="114" cy="213.867" rx="8" ry="12" style="fill-rule:evenodd;clip-rule:evenodd;fill:#777777;stroke:#000000;stroke-width:8;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;"/>
<ellipse cx="194" cy="213.867" rx="8" ry="12" style="fill-rule:evenodd;clip-rule:evenodd;fill:#777777;stroke:#000000;stroke-width:8;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;"/>
<circle cx="130" cy="125.867" r="8" style="fill-rule:evenodd;clip-rule:evenodd;"/>
<circle cx="178" cy="125.867" r="8" style="fill-rule:evenodd;clip-rule:evenodd;"/>
</g>
<g/>
<g/>
<g/>
<g/>
<g/>
<g/>
<g/>
<g/>
<g/>
<g/>
<g/>
<g/>
<g/>
<g/>
<g/>
</svg>
          </div>
          <div class="dialog-text">
          <p>Do you know what makes 37 such a fascinating number?</p>
          </div>
        </div>
        <div class="dialog matt" title="Matt">
          <div class="dialog-head" aria-hidden="true">
          <?xml version="1.0" encoding="utf-8"?>
<!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
<svg width="800px" height="800px" viewBox="0 0 1024 1024" class="icon"  version="1.1" xmlns="http://www.w3.org/2000/svg">
<path d="M419.847493 691.537171c-21.246751-16.838556-32.495766-40.218224-33.494791-61.035395-1.478556-30.8224 5.64199-66.562498 21.361639-107.222791a62.184273 62.184273 0 0 1 5.49963-0.824195c39.783649-4.183415 76.008273 30.237971 80.910985 76.879922 4.900215 46.641951-23.374673 87.841717-63.155824 92.022634a62.578888 62.578888 0 0 1-11.121639 0.179825z" fill="#FFFFFF" /><path d="M427.09042 771.746341h25.327765a24.97561 24.97561 0 0 0 23.297249-15.971902l35.61522-92.147512c0.504507-1.301229 0.896624-2.647415 1.176351-4.016078 2.75481-13.514302-5.969171-26.703922-19.485971-29.458732l-44.818732-9.138576-0.472039-0.089912c-13.566751-2.492566-26.586537 6.483668-29.079102 20.047922l-15.744624 85.666342-36.074771 6.87079A21.129366 21.129366 0 0 0 349.658537 754.263415a17.482927 17.482927 0 0 0 17.482926 17.482926h59.948957z" fill="#5DE4C7" /><path d="M396.462829 720.239141l14.81803-80.61877c3.241834-17.637776 20.165307-29.30638 37.803082-26.064547l0.6144 0.117386 44.82123 9.136078c17.570341 3.581502 28.911766 20.727259 25.332761 38.2976a33.010263 33.010263 0 0 1-1.528508 5.2224l-35.620214 92.15001A32.475785 32.475785 0 0 1 452.418185 779.239024H367.141463c-13.794029 0-24.97561-11.184078-24.975609-24.975609 0-13.74158 9.765463-25.545054 23.26478-28.115044l31.032195-5.90923zM452.418185 764.253659a17.477932 17.477932 0 0 0 16.306576-11.181581l35.617717-92.147512a17.482927 17.482927 0 0 0-12.814985-23.434615l-44.82123-9.131083c-9.827902-1.810732-18.939005 4.473132-20.687297 13.968859l-16.67122 90.711414-41.112351 7.829854A13.636683 13.636683 0 0 0 357.15122 754.263415a9.990244 9.990244 0 0 0 9.990243 9.990244h85.276722z" fill="#524F75" /><path d="M358.649756 761.526322l15.330029-3.873717a7.492683 7.492683 0 0 0-3.673912-14.53081l-15.330029 3.876215a7.492683 7.492683 0 1 0 3.673912 14.528312z" fill="#524F75" /><path d="M536.97561 771.746341h22.088429a24.97561 24.97561 0 0 0 24.878205-22.780253l5.254868-59.546849a25.00558 25.00558 0 0 0-1.463571-10.876878c-4.795317-12.932371-19.166283-19.528429-32.098653-14.73561l-32.33842 11.988293a24.973112 24.973112 0 0 0-16.29159 23.417132v29.004175l-27.782868 5.292332A21.129366 21.129366 0 0 0 462.04878 754.263415a17.482927 17.482927 0 0 0 17.482927 17.482926h57.443903z" fill="#5DE4C7" /><path d="M499.512195 722.017405v-22.805229c0-13.579239 8.449249-25.724878 21.179317-30.442771l32.335922-11.988293c16.81358-6.233912 35.497834 2.342712 41.729249 19.15879 1.675863 4.51559 2.325229 9.343376 1.903141 14.138693l-5.254868 59.546849A32.468293 32.468293 0 0 1 559.064039 779.239024H479.531707c-13.794029 0-24.97561-11.184078-24.975609-24.975609 0-13.74158 9.765463-25.545054 23.26478-28.115044l21.691317-4.130966zM559.064039 764.253659a17.482927 17.482927 0 0 0 17.415493-15.946927l5.25237-59.546849a17.482927 17.482927 0 0 0-23.492058-17.92999l-32.333424 11.988292a17.482927 17.482927 0 0 0-11.408859 16.393991v35.205619l-33.871922 6.4512A13.636683 13.636683 0 0 0 469.541463 754.263415a9.990244 9.990244 0 0 0 9.990244 9.990244h79.532332z" fill="#524F75" /><path d="M471.04 761.526322l15.330029-3.873717a7.492683 7.492683 0 0 0-3.673912-14.53081l-15.330029 3.876215a7.492683 7.492683 0 1 0 3.673912 14.528312z" fill="#524F75" /><path d="M273.123278 545.627161l2.777288 17.375532a24.978107 24.978107 0 0 0 20.754732 20.724761c7.325346 1.161366 12.8 1.630907 16.428956 1.411122 5.434693-0.329678 13.139668-3.241834 23.112429-8.736469a7.48519 7.48519 0 0 0 3.868722-6.888273l-0.207298-4.742868c19.106341 3.254322 36.152195 5.691941 51.137561 7.317854 17.378029 1.888156 45.238322 9.470751 83.583376 22.750282a7.492683 7.492683 0 0 0 9.945288-7.078087v-78.420917a7.492683 7.492683 0 0 0-8.356839-7.442732l-141.941386 16.488897-9.510712-3.18439-0.719297-12.417873a11.718556 11.718556 0 0 0-11.698576-11.03922 12.802498 12.802498 0 0 0-12.667629 10.939318l-1.8432 12.515278c-2.152898 0-4.240859 0.269737-6.23641 0.779239l-34.890927 1.735805a13.719102 13.719102 0 0 0-13.037268 13.699121 13.576741 13.576741 0 0 0 13.042263 13.566752l16.458927 0.646868z" fill="#5DE4C7" /><path d="M256.372137 552.46798a21.069424 21.069424 0 0 1-20.240235-21.054439 21.211785 21.211785 0 0 1 20.157815-21.184312l34.19161-1.700839c0.247259-0.054946 0.49202-0.109893 0.739278-0.159844l0.996527-6.77838a20.297678 20.297678 0 0 1 20.08039-17.340566 19.211239 19.211239 0 0 1 19.178771 18.097327l0.427083 7.355317 3.119453 1.04398 140.283005-16.294087a14.985366 14.985366 0 0 1 16.713678 14.885463v78.420917a14.985366 14.985366 0 0 1-19.890575 14.158673c-37.848039-13.109698-65.266263-20.57241-81.939981-22.383141-12.88242-1.396137-27.245893-3.384195-43.092917-5.966673a14.977873 14.977873 0 0 1-7.282888 9.395824c-10.86439 5.984156-19.473483 9.238478-26.276839 9.653073-4.288312 0.259746-10.237502-0.254751-18.054868-1.493541a32.468293 32.468293 0 0 1-26.981151-26.941191l-1.808234-11.311453-10.319922-0.402108z m76.003278 12.627669a7.492683 7.492683 0 0 1 8.741463-7.712469c18.96398 3.231844 35.862478 5.649483 50.688 7.255415 18.082341 1.963083 46.3872 9.668059 85.229268 23.12242v-78.420917l-141.941385 16.4864a7.432741 7.432741 0 0 1-3.241834-0.339669l-9.510712-3.179395a7.49518 7.49518 0 0 1-5.102517-6.673483l-0.721796-12.417873a4.225873 4.225873 0 0 0-4.21838-3.981112c-2.634927 0-4.870244 1.930615-5.254868 4.538068l-1.840703 12.520273a7.490185 7.490185 0 0 1-7.412761 6.398752c-1.498537 0-2.967102 0.18482-4.385717 0.546965-0.484527 0.124878-0.979044 0.199805-1.478556 0.224781l-34.893424 1.733307a6.223922 6.223922 0 0 0-5.916722 6.216429 6.081561 6.081561 0 0 0 5.844292 6.079064l16.458927 0.649366a7.490185 7.490185 0 0 1 7.105561 6.301346l2.777288 17.375532a17.487922 17.487922 0 0 0 14.528312 14.508331c6.830829 1.083941 11.835941 1.511024 14.803044 1.3312 4.071024-0.244761 10.869385-2.814751 19.94802-7.817365l-0.2048-4.745366z" fill="#524F75" /><path d="M273.29561 553.449522h19.985483a7.492683 7.492683 0 1 0 0-14.985366h-19.985483a7.492683 7.492683 0 0 0 0 14.985366z" fill="#524F75" /><path d="M582.815844 294.51239c5.452176 10.699551-7.530146 31.142088-38.939473 61.32761l-32.490771-63.772722c42.171317-9.068644 65.980566-8.254439 71.430244 2.445112z" fill="#FFC48B" /><path d="M576.541971 298.640859c-2.632429-5.64199-20.832156-7.370302-53.5552-2.332722l21.761249 46.664429c24.343727-22.915122 34.481327-38.564839 31.793951-44.331707z m13.579239-6.331318c7.200468 15.439922-7.692488 37.178693-42.843161 68.677932a7.492683 7.492683 0 0 1-11.790986-2.412644l-30.247961-64.866653a7.492683 7.492683 0 0 1 5.472157-10.542205c46.127454-8.249444 72.139551-6.448702 79.409951 9.14357z" fill="#524F75" /><path d="M600.181385 355.700137c4.775337 9.790439-7.322849 28.130029-36.292058 55.016273l-28.462205-58.365503c38.392507-7.55762 59.978927-6.44121 64.754263 3.34923z" fill="#FFC48B" /><path d="M562.653034 396.919883c11.381385-8.689015 19.810654-16.266615 25.247844-22.652878 5.577054-6.5536 7.330341-10.979278 6.643512-12.974829-0.661854-1.915629-4.600507-4.140956-12.839961-5.589542-8.154537-1.431102-19.398556-1.835707-33.649639-1.176351l14.598244 42.3936z m46.06002-40.507942c5.184937 15.055298-10.442302 33.407376-45.420644 58.695181a7.492683 7.492683 0 0 1-11.473795-3.633951l-21.141854-61.397542a7.492683 7.492683 0 0 1 6.541112-9.912819c42.750751-3.09198 66.257795 1.03399 71.495181 16.249131z" fill="#524F75" /><path d="M614.117776 421.291083c3.546537 10.302439-10.697054 27.028605-42.725776 50.183493l-21.141854-61.397542c39.029385-2.824741 60.321093 0.914107 63.86763 11.214049z" fill="#FFC48B" /><path d="M599.547005 438.426849c6.436215-5.711922 8.78642-9.85038 8.384312-11.923356-0.387122-1.988059-3.981112-4.740371-11.935844-7.320352-7.872312-2.552507-18.951493-4.518088-33.157619-5.849287l8.556644 44.014517c12.475317-7.020644 21.878634-13.351961 28.152507-18.921522z m23.092449-14.783064c3.039532 15.629737-14.990361 31.63161-53.1456 51.80441a7.49518 7.49518 0 0 1-10.859395-5.194927l-12.3904-63.742751a7.492683 7.492683 0 0 1 7.857326-8.903805c42.763239 2.884683 65.468566 10.242498 68.538069 26.037073z" fill="#524F75" /><path d="M622.177405 470.490537c5.53959 8.863844-3.067005 26.888741-25.812293 54.069697l-33.015258-52.830907c33.67961-9.690537 53.287961-10.102634 58.827551-1.23879z" fill="#FFC48B" /><path d="M613.203668 487.011902c3.069502-7.048117 3.404176-11.343922 2.250303-13.054751-1.103922-1.6384-5.00761-2.799766-12.437854-2.385171-7.165502 0.402107-16.606283 2.285268-28.242419 5.664469l23.324722 34.578731c7.160507-9.827902 12.198088-18.122302 15.105248-24.803278z m14.673171-21.43157c8.556644 12.680117-0.31719 33.067707-24.208859 63.735258a7.49518 7.49518 0 0 1-12.12316-0.414595l-34.838479-51.649561a7.492683 7.492683 0 0 1 3.893698-11.313951c36.664195-11.950829 58.630244-13.179629 67.2768-0.357151z" fill="#524F75" /><path d="M651.308956 502.14962c8.206985 4.930185 8.679024 23.219824 1.416117 54.866419l-48.912234-29.391298c23.45959-21.916098 39.289132-30.407805 47.496117-25.475121z" fill="#FFC48B" /><path d="M650.419824 520.112078c0.057444-6.848312-1.1264-10.394849-2.48757-11.281483-1.291239-0.836683-4.782829-0.444566-10.72203 2.480078-5.696937 2.804761-12.720078 7.562615-20.992 14.261073l30.560156 19.84562c2.372683-10.404839 3.581502-18.864078 3.641444-25.305288z m5.671961-23.846712c12.09319 7.852332 11.908371 28.409756 2.6624 63.093385a7.492683 7.492683 0 0 1-11.321444 4.353249l-47.858263-31.077151a7.490185 7.490185 0 0 1-0.83918-11.933347c26.861268-23.394654 45.123434-32.380878 57.356487-24.436136z" fill="#524F75" /><path d="M699.946459 502.511766c8.861346 1.088937 16.19918 16.488898 22.018497 46.204878l-52.820917-6.486166c11.6736-27.568078 21.938576-40.807649 30.80242-39.718712z" fill="#FFC48B" /><path d="M705.121405 517.85678c-2.87719-5.5296-5.284839-7.814868-6.583571-7.929756-0.369639-0.032468-0.966556 0.152351-1.950595 0.826693-1.540995 1.056468-3.356722 2.952117-5.339785 5.699434-3.356722 4.657951-6.945717 11.403863-10.714537 20.197776l32.44082 2.839727c-2.535024-9.240976-5.167454-16.468917-7.852332-21.633874z m-5.277346-22.860175c13.7216 1.201327 22.637893 18.344585 30.267941 51.177522a7.49518 7.49518 0 0 1-7.954732 9.161053l-53.018224-4.63797a7.492683 7.492683 0 0 1-6.343805-10.142595c11.963317-31.244488 23.159883-46.771824 37.04882-45.55801z" fill="#524F75" /><path d="M356.821541 272.883512c29.793405-12.213073 63.970029-15.185171 103.206713 0s84.415063 80.036839 99.879961 138.272468c4.735376 17.832585 7.035629 34.588722 6.900761 50.270908-0.41959 48.003122 35.894946 88.373698 83.673287 93.016663 17.313093 1.683356 62.736234-13.863961 94.442771-42.103883 11.174088-12.907395 18.187239-18.666771 21.046946-17.275629 4.285815 2.085463 1.301229 15.737132 0.796722 17.275629-16.59879 50.805385-31.686556 68.740371-50.842848 85.743766s-41.112351 32.418341-65.443591 42.770732c-9.765463 27.533112-49.099551 52.406322-80.341541 62.344117s-57.771083 14.01881-103.386537 8.354341-78.588254-43.162849-80.40398-81.048351c-1.933112-40.308137 10.379863-88.238829 36.941424-143.794575a7.487688 7.487688 0 0 0-6.089053-10.694557c-52.993249-4.765346-85.341659-11.481288-97.042732-20.150321C293.798088 436.328898 284.721951 408.813268 284.721951 374.436839c0-49.299356 42.306185-89.342751 72.09959-101.553327z" fill="#5DE4C7" /><path d="M356.821541 272.883512C327.028137 285.094088 284.721951 325.137483 284.721951 374.436839c0 34.376429 9.076137 61.892059 35.437893 81.425483 11.701073 8.669034 44.049483 15.387473 97.042732 20.150322a7.492683 7.492683 0 0 1 6.089053 10.694556c-26.561561 55.555746-38.874537 103.488937-36.941424 143.794576 1.818224 37.885502 34.791024 75.383883 80.40398 81.048351s72.144546 1.583454 103.386537-8.354342 70.576078-34.811005 80.341541-62.344117c24.331239-10.35239 46.2848-25.767337 65.443591-42.770731s34.246556-34.93838 50.842848-85.743766c0.50201-1.538498 3.486595-15.190166-0.796722-17.27563-2.859707-1.391141-9.872859 4.368234-21.046946 17.27563-31.706537 28.24242-77.132176 43.787239-94.442771 42.103883-47.778341-4.642966-84.092878-45.013541-83.673287-93.016664 0.137366-15.682185-2.165385-32.438322-6.900761-50.270907-15.464898-58.233132-60.643278-123.0848-99.879961-138.269971s-73.413307-12.213073-103.206713 0z m392.239454 213.873639c2.709854-2.225327 5.259863-3.921171 7.924761-5.100019 4.877737-2.157893 10.145093-2.694868 15.54482-0.067434 6.084059 2.95961 8.993717 8.074615 10.14759 13.93639 0.589424 2.987083 0.674341 6.086556 0.439571 9.438283-0.3072 4.315785-1.258771 9.450771-2.102947 12.028253-15.454907 47.313795-29.710985 69.731902-55.141151 92.299864-20.395083 18.097327-41.674302 32.615649-63.91758 42.865639-13.566751 27.902751-50.171005 53.520234-87.272274 65.318712-36.759102 11.69358-65.503532 14.443395-109.775297 8.943766-51.112585-6.3488-91.278361-48.34279-93.526166-95.202029-1.950595-40.665288 9.435785-87.706849 33.864429-141.287025-49.686478-4.957659-80.146732-11.761015-94.008195-22.030985-29.021659-21.501502-41.501971-52.044176-41.501971-93.463727 0-26.544078 10.394849-52.059161 28.207454-74.102634 15.07278-18.654283 34.870946-33.806985 53.193054-41.317151 36.159688-14.823024 74.162576-15.644722 114.300878-0.109893 43.60242 16.87602 92.035122 84.697288 108.956097 148.402576 5.067551 19.081366 7.547629 37.163707 7.400273 54.249522-0.352156 40.235707 30.090615 74.075161 70.139005 77.971356 15.659707 1.521015 56.764566-15.35001 82.332098-37.763122 5.796839-6.656 10.662088-11.618654 14.795551-15.010342z" fill="#524F75" /><path d="M312.195122 392.117073a7.492683 7.492683 0 0 1 7.492683 7.492683v14.985366a7.492683 7.492683 0 1 1-14.985366 0v-14.985366a7.492683 7.492683 0 0 1 7.492683-7.492683zM347.160976 392.117073a7.492683 7.492683 0 0 1 7.492683 7.492683v14.985366a7.492683 7.492683 0 1 1-14.985366 0v-14.985366a7.492683 7.492683 0 0 1 7.492683-7.492683z" fill="#44756A" /><path d="M405.069424 489.951532c10.911844 1.138888 19.840624 1.138888 26.891239-0.064937 21.561444-3.688898 28.309854-6.211434 41.364605-17.313093a7.492683 7.492683 0 1 0-9.708019-11.416351c-10.619629 9.03118-15.035317 10.679571-34.186615 13.956371-5.50962 0.94158-13.144663 0.94158-22.807727-0.067434a7.492683 7.492683 0 1 0-1.553483 14.905444z" fill="#524F75" /><path d="M419.847493 691.537171c-21.246751-16.838556-32.498263-40.218224-33.497288-61.035395-1.476059-30.8224 5.64199-66.562498 21.361639-107.220293a62.184273 62.184273 0 0 1 5.499629-0.824195c39.783649-4.183415 76.008273 30.237971 80.910986 76.879922 4.900215 46.641951-23.374673 87.841717-63.155825 92.022634-3.746341 0.392117-7.460215 0.444566-11.119141 0.177327z" fill="#FFFFFF" /><path d="M404.689795 261.144976L364.024507 257.973073C383.77522 213.926088 415.264468 195.391688 458.484761 202.369873 501.707551 209.345561 521.920312 239.293815 519.120546 292.214634H463.514849c-0.574439-33.819473-8.117073-52.533698-22.632898-56.147668-14.515824-3.611473-26.579044 4.745366-36.192156 25.07801z" fill="#FFF185" /><path d="M442.690185 228.796566c17.645268 4.390712 26.444176 23.519532 28.072586 55.925385H511.875122C512.449561 239.935688 494.517073 215.774283 457.290927 209.765151 420.821541 203.880898 394.020215 217.3952 375.625678 251.362029l24.640937 1.923122c10.759493-19.953015 25.145444-28.789385 42.42357-24.488585zM352.832937 264.614088l4.353248-9.70802C378.283083 207.867005 412.98919 187.436956 459.678595 194.972098 506.979902 202.607141 529.590322 236.111922 526.600741 292.611746L526.22361 299.707317H456.147044l-0.124878-7.365307c-0.52199-30.759961-6.863298-46.492098-16.950946-49.004644-10.459785-2.602459-19.358595 3.561522-27.605542 21.009483l-2.207844 4.670439L352.832937 264.614088z" fill="#524F75" /><path d="M499.512195 304.702439m-47.453658 0a47.453659 47.453659 0 1 0 94.907317 0 47.453659 47.453659 0 1 0-94.907317 0Z" fill="#FFF185" /><path d="M499.512195 359.64878c-30.345366 0-54.946341-24.600976-54.946341-54.946341s24.600976-54.946341 54.946341-54.946341 54.946341 24.600976 54.946342 54.946341-24.600976 54.946341-54.946342 54.946341z m0-14.985365c22.068449 0 39.960976-17.892527 39.960976-39.960976s-17.892527-39.960976-39.960976-39.960976-39.960976 17.892527-39.960975 39.960976 17.892527 39.960976 39.960975 39.960976z" fill="#524F75" /><path d="M507.004878 297.209756m-24.97561 0a24.97561 24.97561 0 1 0 49.95122 0 24.97561 24.97561 0 1 0-49.95122 0Z" fill="#FFFBDC" /><path d="M312.195122 302.204878m-37.463415 0a37.463415 37.463415 0 1 0 74.92683 0 37.463415 37.463415 0 1 0-74.92683 0Z" fill="#FFFFFF" /><path d="M312.195122 347.160976C287.366868 347.160976 267.239024 327.033132 267.239024 302.204878S287.366868 257.24878 312.195122 257.24878s44.956098 20.127844 44.956098 44.956098-20.127844 44.956098-44.956098 44.956098z m0-14.985366c16.551337 0 29.970732-13.419395 29.970732-29.970732S328.746459 272.234146 312.195122 272.234146 282.22439 285.653541 282.22439 302.204878s13.419395 29.970732 29.970732 29.970732z" fill="#524F75" /><path d="M292.446907 310.798985A11.239024 11.239024 0 1 0 289.717073 303.22638l8.331864 1.211318-5.60203 6.361287z" fill="#232323" /><path d="M498.458224 472.543532c7.662517-16.416468 12.495298-30.342868 14.498342-41.781698 1.153873-19.381073 1.153873-32.445815 0-39.194224-0.3072-1.790751-2.497561-4.810302-6.571083-9.058654-13.621698-3.711376-22.528-17.178224-20.235239-31.431805C488.987473 333.431883 504.762068 320.826693 522.599649 321.950595l21.511492 1.356176c15.464898 0.976546 27.732917 12.879922 29.558635 27.850302 4.770341 2.769795 9.588137 7.442732 9.448273 13.389425-0.304702 13.002302-8.569132 18.269659-18.11481 19.615843l-13.444371 1.893152 7.357815 35.273053c1.940605 11.853424 6.086556 23.487063 6.086556 38.122771l-6.086556 45.655415" fill="#5DE4C7" /><path d="M552.273171 426.650849c0.279727 1.41362 0.589424 2.882185 0.976546 4.62798 0.147356 0.674341 0.299707 1.358673 0.507005 2.280273l0.507005 2.265288c2.282771 10.23001 3.204371 16.131746 3.246829 23.139903l-6.016624 45.153405a7.492683 7.492683 0 1 0 14.852995 1.978068l6.084058-45.655415c0.044956-0.32718 0.067434-0.659356 0.067435-0.989034 0-8.59161-1.048976-15.429932-3.608976-26.891239l-0.509503-2.277776-0.494517-2.225326a184.817015 184.817015 0 0 1-0.909112-4.318283 124.42599 124.42599 0 0 1-0.661853-3.621464l-5.779357-27.757892 5.517113-0.776742c14.513327-2.043005 24.196371-11.179083 24.561014-26.858771 0.172332-7.387785-3.88121-13.546771-10.107629-18.054868A39.30162 39.30162 0 0 0 544.585678 315.831571l-21.511493-1.356176C501.382868 313.104234 482.2016 328.431766 478.752468 349.888312c-2.762302 17.195707 7.357815 33.67961 23.527025 39.196722 1.176351 1.286244 2.092956 2.385171 2.739824 3.2768 0.284722 0.392117 0.494517 0.714302 0.629385 0.949073 0.94158 6.13401 0.9216 18.474459-0.144858 36.574283-1.920624 10.634615-6.521132 23.829229-13.83399 39.491434a7.492683 7.492683 0 0 0 13.576741 6.341308c7.919766-16.963434 12.959844-31.486751 15.090264-43.657366 0.049951-0.279727 0.08242-0.561951 0.099902-0.846673 1.188839-19.940527 1.188839-33.409873-0.094907-40.902556-0.654361-3.826263-3.404176-7.620059-8.546654-12.982322a7.500176 7.500176 0 0 0-3.436644-2.043005c-10.037698-2.734829-16.473912-12.652644-14.808039-23.015025a27.208429 27.208429 0 0 1 28.577093-22.837697l21.511492 1.356175a24.311259 24.311259 0 0 1 22.595435 21.27922 7.48519 7.48519 0 0 0 3.673912 5.572058c3.69639 2.145405 5.766868 4.767844 5.721912 6.733425-0.179824 7.739941-3.941151 11.28398-11.671102 12.372917l-13.441874 1.893151a7.492683 7.492683 0 0 0-6.291356 8.948761l7.325347 35.118205c0.209795 1.261268 0.449561 2.562498 0.721795 3.943649z" fill="#524F75" /><path d="M555.707317 528.234146m-8.741463 0a8.741463 8.741463 0 1 0 17.482926 0 8.741463 8.741463 0 1 0-17.482926 0Z" fill="#524F75" /><path d="M514.05799 326.683473l-2.340214 15.764605a7.492683 7.492683 0 1 0 14.820526 2.200351l2.342713-15.764605a7.492683 7.492683 0 0 0-14.823025-2.200351zM539.0336 329.181034l-2.340215 15.764605a7.492683 7.492683 0 1 0 14.820527 2.200351l2.342712-15.764605a7.492683 7.492683 0 0 0-14.823024-2.200351z" fill="#524F75" /><path d="M389.619512 289.717073m-47.453658 0a47.453659 47.453659 0 1 0 94.907317 0 47.453659 47.453659 0 1 0-94.907317 0Z" fill="#FFFFFF" /><path d="M389.619512 344.663415C359.274146 344.663415 334.673171 320.062439 334.673171 289.717073S359.274146 234.770732 389.619512 234.770732s54.946341 24.600976 54.946342 54.946341-24.600976 54.946341-54.946342 54.946342z m0-14.985366c22.068449 0 39.960976-17.892527 39.960976-39.960976S411.687961 249.756098 389.619512 249.756098 349.658537 267.648624 349.658537 289.717073s17.892527 39.960976 39.960975 39.960976z" fill="#524F75" /><path d="M365.787785 302.007571A14.985366 14.985366 0 1 0 362.146341 291.909932l11.109152 1.615922-7.467708 8.481717z" fill="#232323" />
</svg>

          </div>
          <div class="dialog-text">
          <p>Well, it's not just any number—it's a prime! And not just any prime, but one with remarkable properties.</p>
          </div>
        </div>
<div class="paragraph">
<p>Thirty-seven is truly magnificent – a prime number that stands boldly in its mathematical uniqueness. It&#8217;s the twelfth prime, sitting proudly between 31 and 41 in the sequence of these indivisible numbers.</p>
</div>
<div class="paragraph">
<p>May this year be as unique and irreducible as the number itself – full of moments that can&#8217;t be divided or diminished.</p>
</div>]]></content><author><name>ohmycloud</name></author><summary type="html"><![CDATA[Do you know what makes 37 such a fascinating number?]]></summary></entry><entry><title type="html">Understanding Rust’s Conversion Traits</title><link href="https://ohmycloud.github.io/2025/05/06/rust-conversion-traits.html" rel="alternate" type="text/html" title="Understanding Rust’s Conversion Traits" /><published>2025-05-06T00:00:00+00:00</published><updated>2025-05-06T00:00:00+00:00</updated><id>https://ohmycloud.github.io/2025/05/06/rust-conversion-traits</id><content type="html" xml:base="https://ohmycloud.github.io/2025/05/06/rust-conversion-traits.html"><![CDATA[<div class="sect1">
<h2 id="introduction">Introduction</h2>
<div class="sectionbody">
<div class="paragraph">
<p>Rust&#8217;s type system is both powerful and strict, enforcing strong boundaries between different types. However, we often need to convert values between related types - for example, from a tuple like <code>(i32, i32)</code> to a custom <code>Point</code> struct, or from a <code>String</code> to a <code>&amp;str</code>.</p>
</div>
        <div class="dialog cop" title="Cop">
          <div class="dialog-head" aria-hidden="true">
          <?xml version="1.0" ?>
<!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
<svg width="800px" height="800px" viewBox="0 0 300 300" id="giraffe" version="1.1" xml:space="preserve" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g>
<path d="   M62,61.867h60v28H88.013c-7.739,0-16.47-5.734-19.521-12.853L62,61.867z" style="fill-rule:evenodd;clip-rule:evenodd;fill:#FFDD95;stroke:#000000;stroke-width:8;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;"/>
<path d="   M246,61.867h-60v28h33.987c7.739,0,16.47-5.734,19.521-12.853L246,61.867z" style="fill-rule:evenodd;clip-rule:evenodd;fill:#FFDD95;stroke:#000000;stroke-width:8;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;"/>
<path d="   M130,39.895c0-5.539,4.439-10.028,10-10.028c5.523,0,10,4.487,10,10.028v25.972h-20V39.895z" style="fill-rule:evenodd;clip-rule:evenodd;fill:#DDDDDD;stroke:#000000;stroke-width:7.7333;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;"/>
<path d="   M162,39.895c0-5.539,4.439-10.028,10-10.028c5.523,0,10,4.487,10,10.028v25.972h-20V39.895z" style="fill-rule:evenodd;clip-rule:evenodd;fill:#DDDDDD;stroke:#000000;stroke-width:7.7333;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;"/>
<path d="   M120.793,277.867h66.413l22.63-192.163c1.55-13.165-8.069-23.837-21.495-23.837h-68.684c-13.422,0-23.04,10.712-21.495,23.837   L120.793,277.867z" style="fill-rule:evenodd;clip-rule:evenodd;fill:#FBAD4A;stroke:#000000;stroke-width:8;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;"/>
<ellipse cx="154" cy="213.867" rx="64" ry="32" style="fill-rule:evenodd;clip-rule:evenodd;fill:#FFDD95;stroke:#000000;stroke-width:8;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;"/>
<ellipse cx="114" cy="213.867" rx="8" ry="12" style="fill-rule:evenodd;clip-rule:evenodd;fill:#777777;stroke:#000000;stroke-width:8;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;"/>
<ellipse cx="194" cy="213.867" rx="8" ry="12" style="fill-rule:evenodd;clip-rule:evenodd;fill:#777777;stroke:#000000;stroke-width:8;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;"/>
<circle cx="130" cy="125.867" r="8" style="fill-rule:evenodd;clip-rule:evenodd;"/>
<circle cx="178" cy="125.867" r="8" style="fill-rule:evenodd;clip-rule:evenodd;"/>
</g>
<g/>
<g/>
<g/>
<g/>
<g/>
<g/>
<g/>
<g/>
<g/>
<g/>
<g/>
<g/>
<g/>
<g/>
<g/>
</svg>
          </div>
          <div class="dialog-text">
          <p>Some concepts are confusing to beginners, which are difficult to understand.</p>
          </div>
        </div>
        <div class="dialog matt" title="Matt">
          <div class="dialog-head" aria-hidden="true">
          <?xml version="1.0" encoding="utf-8"?>
<!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
<svg width="800px" height="800px" viewBox="0 0 1024 1024" class="icon"  version="1.1" xmlns="http://www.w3.org/2000/svg">
<path d="M419.847493 691.537171c-21.246751-16.838556-32.495766-40.218224-33.494791-61.035395-1.478556-30.8224 5.64199-66.562498 21.361639-107.222791a62.184273 62.184273 0 0 1 5.49963-0.824195c39.783649-4.183415 76.008273 30.237971 80.910985 76.879922 4.900215 46.641951-23.374673 87.841717-63.155824 92.022634a62.578888 62.578888 0 0 1-11.121639 0.179825z" fill="#FFFFFF" /><path d="M427.09042 771.746341h25.327765a24.97561 24.97561 0 0 0 23.297249-15.971902l35.61522-92.147512c0.504507-1.301229 0.896624-2.647415 1.176351-4.016078 2.75481-13.514302-5.969171-26.703922-19.485971-29.458732l-44.818732-9.138576-0.472039-0.089912c-13.566751-2.492566-26.586537 6.483668-29.079102 20.047922l-15.744624 85.666342-36.074771 6.87079A21.129366 21.129366 0 0 0 349.658537 754.263415a17.482927 17.482927 0 0 0 17.482926 17.482926h59.948957z" fill="#5DE4C7" /><path d="M396.462829 720.239141l14.81803-80.61877c3.241834-17.637776 20.165307-29.30638 37.803082-26.064547l0.6144 0.117386 44.82123 9.136078c17.570341 3.581502 28.911766 20.727259 25.332761 38.2976a33.010263 33.010263 0 0 1-1.528508 5.2224l-35.620214 92.15001A32.475785 32.475785 0 0 1 452.418185 779.239024H367.141463c-13.794029 0-24.97561-11.184078-24.975609-24.975609 0-13.74158 9.765463-25.545054 23.26478-28.115044l31.032195-5.90923zM452.418185 764.253659a17.477932 17.477932 0 0 0 16.306576-11.181581l35.617717-92.147512a17.482927 17.482927 0 0 0-12.814985-23.434615l-44.82123-9.131083c-9.827902-1.810732-18.939005 4.473132-20.687297 13.968859l-16.67122 90.711414-41.112351 7.829854A13.636683 13.636683 0 0 0 357.15122 754.263415a9.990244 9.990244 0 0 0 9.990243 9.990244h85.276722z" fill="#524F75" /><path d="M358.649756 761.526322l15.330029-3.873717a7.492683 7.492683 0 0 0-3.673912-14.53081l-15.330029 3.876215a7.492683 7.492683 0 1 0 3.673912 14.528312z" fill="#524F75" /><path d="M536.97561 771.746341h22.088429a24.97561 24.97561 0 0 0 24.878205-22.780253l5.254868-59.546849a25.00558 25.00558 0 0 0-1.463571-10.876878c-4.795317-12.932371-19.166283-19.528429-32.098653-14.73561l-32.33842 11.988293a24.973112 24.973112 0 0 0-16.29159 23.417132v29.004175l-27.782868 5.292332A21.129366 21.129366 0 0 0 462.04878 754.263415a17.482927 17.482927 0 0 0 17.482927 17.482926h57.443903z" fill="#5DE4C7" /><path d="M499.512195 722.017405v-22.805229c0-13.579239 8.449249-25.724878 21.179317-30.442771l32.335922-11.988293c16.81358-6.233912 35.497834 2.342712 41.729249 19.15879 1.675863 4.51559 2.325229 9.343376 1.903141 14.138693l-5.254868 59.546849A32.468293 32.468293 0 0 1 559.064039 779.239024H479.531707c-13.794029 0-24.97561-11.184078-24.975609-24.975609 0-13.74158 9.765463-25.545054 23.26478-28.115044l21.691317-4.130966zM559.064039 764.253659a17.482927 17.482927 0 0 0 17.415493-15.946927l5.25237-59.546849a17.482927 17.482927 0 0 0-23.492058-17.92999l-32.333424 11.988292a17.482927 17.482927 0 0 0-11.408859 16.393991v35.205619l-33.871922 6.4512A13.636683 13.636683 0 0 0 469.541463 754.263415a9.990244 9.990244 0 0 0 9.990244 9.990244h79.532332z" fill="#524F75" /><path d="M471.04 761.526322l15.330029-3.873717a7.492683 7.492683 0 0 0-3.673912-14.53081l-15.330029 3.876215a7.492683 7.492683 0 1 0 3.673912 14.528312z" fill="#524F75" /><path d="M273.123278 545.627161l2.777288 17.375532a24.978107 24.978107 0 0 0 20.754732 20.724761c7.325346 1.161366 12.8 1.630907 16.428956 1.411122 5.434693-0.329678 13.139668-3.241834 23.112429-8.736469a7.48519 7.48519 0 0 0 3.868722-6.888273l-0.207298-4.742868c19.106341 3.254322 36.152195 5.691941 51.137561 7.317854 17.378029 1.888156 45.238322 9.470751 83.583376 22.750282a7.492683 7.492683 0 0 0 9.945288-7.078087v-78.420917a7.492683 7.492683 0 0 0-8.356839-7.442732l-141.941386 16.488897-9.510712-3.18439-0.719297-12.417873a11.718556 11.718556 0 0 0-11.698576-11.03922 12.802498 12.802498 0 0 0-12.667629 10.939318l-1.8432 12.515278c-2.152898 0-4.240859 0.269737-6.23641 0.779239l-34.890927 1.735805a13.719102 13.719102 0 0 0-13.037268 13.699121 13.576741 13.576741 0 0 0 13.042263 13.566752l16.458927 0.646868z" fill="#5DE4C7" /><path d="M256.372137 552.46798a21.069424 21.069424 0 0 1-20.240235-21.054439 21.211785 21.211785 0 0 1 20.157815-21.184312l34.19161-1.700839c0.247259-0.054946 0.49202-0.109893 0.739278-0.159844l0.996527-6.77838a20.297678 20.297678 0 0 1 20.08039-17.340566 19.211239 19.211239 0 0 1 19.178771 18.097327l0.427083 7.355317 3.119453 1.04398 140.283005-16.294087a14.985366 14.985366 0 0 1 16.713678 14.885463v78.420917a14.985366 14.985366 0 0 1-19.890575 14.158673c-37.848039-13.109698-65.266263-20.57241-81.939981-22.383141-12.88242-1.396137-27.245893-3.384195-43.092917-5.966673a14.977873 14.977873 0 0 1-7.282888 9.395824c-10.86439 5.984156-19.473483 9.238478-26.276839 9.653073-4.288312 0.259746-10.237502-0.254751-18.054868-1.493541a32.468293 32.468293 0 0 1-26.981151-26.941191l-1.808234-11.311453-10.319922-0.402108z m76.003278 12.627669a7.492683 7.492683 0 0 1 8.741463-7.712469c18.96398 3.231844 35.862478 5.649483 50.688 7.255415 18.082341 1.963083 46.3872 9.668059 85.229268 23.12242v-78.420917l-141.941385 16.4864a7.432741 7.432741 0 0 1-3.241834-0.339669l-9.510712-3.179395a7.49518 7.49518 0 0 1-5.102517-6.673483l-0.721796-12.417873a4.225873 4.225873 0 0 0-4.21838-3.981112c-2.634927 0-4.870244 1.930615-5.254868 4.538068l-1.840703 12.520273a7.490185 7.490185 0 0 1-7.412761 6.398752c-1.498537 0-2.967102 0.18482-4.385717 0.546965-0.484527 0.124878-0.979044 0.199805-1.478556 0.224781l-34.893424 1.733307a6.223922 6.223922 0 0 0-5.916722 6.216429 6.081561 6.081561 0 0 0 5.844292 6.079064l16.458927 0.649366a7.490185 7.490185 0 0 1 7.105561 6.301346l2.777288 17.375532a17.487922 17.487922 0 0 0 14.528312 14.508331c6.830829 1.083941 11.835941 1.511024 14.803044 1.3312 4.071024-0.244761 10.869385-2.814751 19.94802-7.817365l-0.2048-4.745366z" fill="#524F75" /><path d="M273.29561 553.449522h19.985483a7.492683 7.492683 0 1 0 0-14.985366h-19.985483a7.492683 7.492683 0 0 0 0 14.985366z" fill="#524F75" /><path d="M582.815844 294.51239c5.452176 10.699551-7.530146 31.142088-38.939473 61.32761l-32.490771-63.772722c42.171317-9.068644 65.980566-8.254439 71.430244 2.445112z" fill="#FFC48B" /><path d="M576.541971 298.640859c-2.632429-5.64199-20.832156-7.370302-53.5552-2.332722l21.761249 46.664429c24.343727-22.915122 34.481327-38.564839 31.793951-44.331707z m13.579239-6.331318c7.200468 15.439922-7.692488 37.178693-42.843161 68.677932a7.492683 7.492683 0 0 1-11.790986-2.412644l-30.247961-64.866653a7.492683 7.492683 0 0 1 5.472157-10.542205c46.127454-8.249444 72.139551-6.448702 79.409951 9.14357z" fill="#524F75" /><path d="M600.181385 355.700137c4.775337 9.790439-7.322849 28.130029-36.292058 55.016273l-28.462205-58.365503c38.392507-7.55762 59.978927-6.44121 64.754263 3.34923z" fill="#FFC48B" /><path d="M562.653034 396.919883c11.381385-8.689015 19.810654-16.266615 25.247844-22.652878 5.577054-6.5536 7.330341-10.979278 6.643512-12.974829-0.661854-1.915629-4.600507-4.140956-12.839961-5.589542-8.154537-1.431102-19.398556-1.835707-33.649639-1.176351l14.598244 42.3936z m46.06002-40.507942c5.184937 15.055298-10.442302 33.407376-45.420644 58.695181a7.492683 7.492683 0 0 1-11.473795-3.633951l-21.141854-61.397542a7.492683 7.492683 0 0 1 6.541112-9.912819c42.750751-3.09198 66.257795 1.03399 71.495181 16.249131z" fill="#524F75" /><path d="M614.117776 421.291083c3.546537 10.302439-10.697054 27.028605-42.725776 50.183493l-21.141854-61.397542c39.029385-2.824741 60.321093 0.914107 63.86763 11.214049z" fill="#FFC48B" /><path d="M599.547005 438.426849c6.436215-5.711922 8.78642-9.85038 8.384312-11.923356-0.387122-1.988059-3.981112-4.740371-11.935844-7.320352-7.872312-2.552507-18.951493-4.518088-33.157619-5.849287l8.556644 44.014517c12.475317-7.020644 21.878634-13.351961 28.152507-18.921522z m23.092449-14.783064c3.039532 15.629737-14.990361 31.63161-53.1456 51.80441a7.49518 7.49518 0 0 1-10.859395-5.194927l-12.3904-63.742751a7.492683 7.492683 0 0 1 7.857326-8.903805c42.763239 2.884683 65.468566 10.242498 68.538069 26.037073z" fill="#524F75" /><path d="M622.177405 470.490537c5.53959 8.863844-3.067005 26.888741-25.812293 54.069697l-33.015258-52.830907c33.67961-9.690537 53.287961-10.102634 58.827551-1.23879z" fill="#FFC48B" /><path d="M613.203668 487.011902c3.069502-7.048117 3.404176-11.343922 2.250303-13.054751-1.103922-1.6384-5.00761-2.799766-12.437854-2.385171-7.165502 0.402107-16.606283 2.285268-28.242419 5.664469l23.324722 34.578731c7.160507-9.827902 12.198088-18.122302 15.105248-24.803278z m14.673171-21.43157c8.556644 12.680117-0.31719 33.067707-24.208859 63.735258a7.49518 7.49518 0 0 1-12.12316-0.414595l-34.838479-51.649561a7.492683 7.492683 0 0 1 3.893698-11.313951c36.664195-11.950829 58.630244-13.179629 67.2768-0.357151z" fill="#524F75" /><path d="M651.308956 502.14962c8.206985 4.930185 8.679024 23.219824 1.416117 54.866419l-48.912234-29.391298c23.45959-21.916098 39.289132-30.407805 47.496117-25.475121z" fill="#FFC48B" /><path d="M650.419824 520.112078c0.057444-6.848312-1.1264-10.394849-2.48757-11.281483-1.291239-0.836683-4.782829-0.444566-10.72203 2.480078-5.696937 2.804761-12.720078 7.562615-20.992 14.261073l30.560156 19.84562c2.372683-10.404839 3.581502-18.864078 3.641444-25.305288z m5.671961-23.846712c12.09319 7.852332 11.908371 28.409756 2.6624 63.093385a7.492683 7.492683 0 0 1-11.321444 4.353249l-47.858263-31.077151a7.490185 7.490185 0 0 1-0.83918-11.933347c26.861268-23.394654 45.123434-32.380878 57.356487-24.436136z" fill="#524F75" /><path d="M699.946459 502.511766c8.861346 1.088937 16.19918 16.488898 22.018497 46.204878l-52.820917-6.486166c11.6736-27.568078 21.938576-40.807649 30.80242-39.718712z" fill="#FFC48B" /><path d="M705.121405 517.85678c-2.87719-5.5296-5.284839-7.814868-6.583571-7.929756-0.369639-0.032468-0.966556 0.152351-1.950595 0.826693-1.540995 1.056468-3.356722 2.952117-5.339785 5.699434-3.356722 4.657951-6.945717 11.403863-10.714537 20.197776l32.44082 2.839727c-2.535024-9.240976-5.167454-16.468917-7.852332-21.633874z m-5.277346-22.860175c13.7216 1.201327 22.637893 18.344585 30.267941 51.177522a7.49518 7.49518 0 0 1-7.954732 9.161053l-53.018224-4.63797a7.492683 7.492683 0 0 1-6.343805-10.142595c11.963317-31.244488 23.159883-46.771824 37.04882-45.55801z" fill="#524F75" /><path d="M356.821541 272.883512c29.793405-12.213073 63.970029-15.185171 103.206713 0s84.415063 80.036839 99.879961 138.272468c4.735376 17.832585 7.035629 34.588722 6.900761 50.270908-0.41959 48.003122 35.894946 88.373698 83.673287 93.016663 17.313093 1.683356 62.736234-13.863961 94.442771-42.103883 11.174088-12.907395 18.187239-18.666771 21.046946-17.275629 4.285815 2.085463 1.301229 15.737132 0.796722 17.275629-16.59879 50.805385-31.686556 68.740371-50.842848 85.743766s-41.112351 32.418341-65.443591 42.770732c-9.765463 27.533112-49.099551 52.406322-80.341541 62.344117s-57.771083 14.01881-103.386537 8.354341-78.588254-43.162849-80.40398-81.048351c-1.933112-40.308137 10.379863-88.238829 36.941424-143.794575a7.487688 7.487688 0 0 0-6.089053-10.694557c-52.993249-4.765346-85.341659-11.481288-97.042732-20.150321C293.798088 436.328898 284.721951 408.813268 284.721951 374.436839c0-49.299356 42.306185-89.342751 72.09959-101.553327z" fill="#5DE4C7" /><path d="M356.821541 272.883512C327.028137 285.094088 284.721951 325.137483 284.721951 374.436839c0 34.376429 9.076137 61.892059 35.437893 81.425483 11.701073 8.669034 44.049483 15.387473 97.042732 20.150322a7.492683 7.492683 0 0 1 6.089053 10.694556c-26.561561 55.555746-38.874537 103.488937-36.941424 143.794576 1.818224 37.885502 34.791024 75.383883 80.40398 81.048351s72.144546 1.583454 103.386537-8.354342 70.576078-34.811005 80.341541-62.344117c24.331239-10.35239 46.2848-25.767337 65.443591-42.770731s34.246556-34.93838 50.842848-85.743766c0.50201-1.538498 3.486595-15.190166-0.796722-17.27563-2.859707-1.391141-9.872859 4.368234-21.046946 17.27563-31.706537 28.24242-77.132176 43.787239-94.442771 42.103883-47.778341-4.642966-84.092878-45.013541-83.673287-93.016664 0.137366-15.682185-2.165385-32.438322-6.900761-50.270907-15.464898-58.233132-60.643278-123.0848-99.879961-138.269971s-73.413307-12.213073-103.206713 0z m392.239454 213.873639c2.709854-2.225327 5.259863-3.921171 7.924761-5.100019 4.877737-2.157893 10.145093-2.694868 15.54482-0.067434 6.084059 2.95961 8.993717 8.074615 10.14759 13.93639 0.589424 2.987083 0.674341 6.086556 0.439571 9.438283-0.3072 4.315785-1.258771 9.450771-2.102947 12.028253-15.454907 47.313795-29.710985 69.731902-55.141151 92.299864-20.395083 18.097327-41.674302 32.615649-63.91758 42.865639-13.566751 27.902751-50.171005 53.520234-87.272274 65.318712-36.759102 11.69358-65.503532 14.443395-109.775297 8.943766-51.112585-6.3488-91.278361-48.34279-93.526166-95.202029-1.950595-40.665288 9.435785-87.706849 33.864429-141.287025-49.686478-4.957659-80.146732-11.761015-94.008195-22.030985-29.021659-21.501502-41.501971-52.044176-41.501971-93.463727 0-26.544078 10.394849-52.059161 28.207454-74.102634 15.07278-18.654283 34.870946-33.806985 53.193054-41.317151 36.159688-14.823024 74.162576-15.644722 114.300878-0.109893 43.60242 16.87602 92.035122 84.697288 108.956097 148.402576 5.067551 19.081366 7.547629 37.163707 7.400273 54.249522-0.352156 40.235707 30.090615 74.075161 70.139005 77.971356 15.659707 1.521015 56.764566-15.35001 82.332098-37.763122 5.796839-6.656 10.662088-11.618654 14.795551-15.010342z" fill="#524F75" /><path d="M312.195122 392.117073a7.492683 7.492683 0 0 1 7.492683 7.492683v14.985366a7.492683 7.492683 0 1 1-14.985366 0v-14.985366a7.492683 7.492683 0 0 1 7.492683-7.492683zM347.160976 392.117073a7.492683 7.492683 0 0 1 7.492683 7.492683v14.985366a7.492683 7.492683 0 1 1-14.985366 0v-14.985366a7.492683 7.492683 0 0 1 7.492683-7.492683z" fill="#44756A" /><path d="M405.069424 489.951532c10.911844 1.138888 19.840624 1.138888 26.891239-0.064937 21.561444-3.688898 28.309854-6.211434 41.364605-17.313093a7.492683 7.492683 0 1 0-9.708019-11.416351c-10.619629 9.03118-15.035317 10.679571-34.186615 13.956371-5.50962 0.94158-13.144663 0.94158-22.807727-0.067434a7.492683 7.492683 0 1 0-1.553483 14.905444z" fill="#524F75" /><path d="M419.847493 691.537171c-21.246751-16.838556-32.498263-40.218224-33.497288-61.035395-1.476059-30.8224 5.64199-66.562498 21.361639-107.220293a62.184273 62.184273 0 0 1 5.499629-0.824195c39.783649-4.183415 76.008273 30.237971 80.910986 76.879922 4.900215 46.641951-23.374673 87.841717-63.155825 92.022634-3.746341 0.392117-7.460215 0.444566-11.119141 0.177327z" fill="#FFFFFF" /><path d="M404.689795 261.144976L364.024507 257.973073C383.77522 213.926088 415.264468 195.391688 458.484761 202.369873 501.707551 209.345561 521.920312 239.293815 519.120546 292.214634H463.514849c-0.574439-33.819473-8.117073-52.533698-22.632898-56.147668-14.515824-3.611473-26.579044 4.745366-36.192156 25.07801z" fill="#FFF185" /><path d="M442.690185 228.796566c17.645268 4.390712 26.444176 23.519532 28.072586 55.925385H511.875122C512.449561 239.935688 494.517073 215.774283 457.290927 209.765151 420.821541 203.880898 394.020215 217.3952 375.625678 251.362029l24.640937 1.923122c10.759493-19.953015 25.145444-28.789385 42.42357-24.488585zM352.832937 264.614088l4.353248-9.70802C378.283083 207.867005 412.98919 187.436956 459.678595 194.972098 506.979902 202.607141 529.590322 236.111922 526.600741 292.611746L526.22361 299.707317H456.147044l-0.124878-7.365307c-0.52199-30.759961-6.863298-46.492098-16.950946-49.004644-10.459785-2.602459-19.358595 3.561522-27.605542 21.009483l-2.207844 4.670439L352.832937 264.614088z" fill="#524F75" /><path d="M499.512195 304.702439m-47.453658 0a47.453659 47.453659 0 1 0 94.907317 0 47.453659 47.453659 0 1 0-94.907317 0Z" fill="#FFF185" /><path d="M499.512195 359.64878c-30.345366 0-54.946341-24.600976-54.946341-54.946341s24.600976-54.946341 54.946341-54.946341 54.946341 24.600976 54.946342 54.946341-24.600976 54.946341-54.946342 54.946341z m0-14.985365c22.068449 0 39.960976-17.892527 39.960976-39.960976s-17.892527-39.960976-39.960976-39.960976-39.960976 17.892527-39.960975 39.960976 17.892527 39.960976 39.960975 39.960976z" fill="#524F75" /><path d="M507.004878 297.209756m-24.97561 0a24.97561 24.97561 0 1 0 49.95122 0 24.97561 24.97561 0 1 0-49.95122 0Z" fill="#FFFBDC" /><path d="M312.195122 302.204878m-37.463415 0a37.463415 37.463415 0 1 0 74.92683 0 37.463415 37.463415 0 1 0-74.92683 0Z" fill="#FFFFFF" /><path d="M312.195122 347.160976C287.366868 347.160976 267.239024 327.033132 267.239024 302.204878S287.366868 257.24878 312.195122 257.24878s44.956098 20.127844 44.956098 44.956098-20.127844 44.956098-44.956098 44.956098z m0-14.985366c16.551337 0 29.970732-13.419395 29.970732-29.970732S328.746459 272.234146 312.195122 272.234146 282.22439 285.653541 282.22439 302.204878s13.419395 29.970732 29.970732 29.970732z" fill="#524F75" /><path d="M292.446907 310.798985A11.239024 11.239024 0 1 0 289.717073 303.22638l8.331864 1.211318-5.60203 6.361287z" fill="#232323" /><path d="M498.458224 472.543532c7.662517-16.416468 12.495298-30.342868 14.498342-41.781698 1.153873-19.381073 1.153873-32.445815 0-39.194224-0.3072-1.790751-2.497561-4.810302-6.571083-9.058654-13.621698-3.711376-22.528-17.178224-20.235239-31.431805C488.987473 333.431883 504.762068 320.826693 522.599649 321.950595l21.511492 1.356176c15.464898 0.976546 27.732917 12.879922 29.558635 27.850302 4.770341 2.769795 9.588137 7.442732 9.448273 13.389425-0.304702 13.002302-8.569132 18.269659-18.11481 19.615843l-13.444371 1.893152 7.357815 35.273053c1.940605 11.853424 6.086556 23.487063 6.086556 38.122771l-6.086556 45.655415" fill="#5DE4C7" /><path d="M552.273171 426.650849c0.279727 1.41362 0.589424 2.882185 0.976546 4.62798 0.147356 0.674341 0.299707 1.358673 0.507005 2.280273l0.507005 2.265288c2.282771 10.23001 3.204371 16.131746 3.246829 23.139903l-6.016624 45.153405a7.492683 7.492683 0 1 0 14.852995 1.978068l6.084058-45.655415c0.044956-0.32718 0.067434-0.659356 0.067435-0.989034 0-8.59161-1.048976-15.429932-3.608976-26.891239l-0.509503-2.277776-0.494517-2.225326a184.817015 184.817015 0 0 1-0.909112-4.318283 124.42599 124.42599 0 0 1-0.661853-3.621464l-5.779357-27.757892 5.517113-0.776742c14.513327-2.043005 24.196371-11.179083 24.561014-26.858771 0.172332-7.387785-3.88121-13.546771-10.107629-18.054868A39.30162 39.30162 0 0 0 544.585678 315.831571l-21.511493-1.356176C501.382868 313.104234 482.2016 328.431766 478.752468 349.888312c-2.762302 17.195707 7.357815 33.67961 23.527025 39.196722 1.176351 1.286244 2.092956 2.385171 2.739824 3.2768 0.284722 0.392117 0.494517 0.714302 0.629385 0.949073 0.94158 6.13401 0.9216 18.474459-0.144858 36.574283-1.920624 10.634615-6.521132 23.829229-13.83399 39.491434a7.492683 7.492683 0 0 0 13.576741 6.341308c7.919766-16.963434 12.959844-31.486751 15.090264-43.657366 0.049951-0.279727 0.08242-0.561951 0.099902-0.846673 1.188839-19.940527 1.188839-33.409873-0.094907-40.902556-0.654361-3.826263-3.404176-7.620059-8.546654-12.982322a7.500176 7.500176 0 0 0-3.436644-2.043005c-10.037698-2.734829-16.473912-12.652644-14.808039-23.015025a27.208429 27.208429 0 0 1 28.577093-22.837697l21.511492 1.356175a24.311259 24.311259 0 0 1 22.595435 21.27922 7.48519 7.48519 0 0 0 3.673912 5.572058c3.69639 2.145405 5.766868 4.767844 5.721912 6.733425-0.179824 7.739941-3.941151 11.28398-11.671102 12.372917l-13.441874 1.893151a7.492683 7.492683 0 0 0-6.291356 8.948761l7.325347 35.118205c0.209795 1.261268 0.449561 2.562498 0.721795 3.943649z" fill="#524F75" /><path d="M555.707317 528.234146m-8.741463 0a8.741463 8.741463 0 1 0 17.482926 0 8.741463 8.741463 0 1 0-17.482926 0Z" fill="#524F75" /><path d="M514.05799 326.683473l-2.340214 15.764605a7.492683 7.492683 0 1 0 14.820526 2.200351l2.342713-15.764605a7.492683 7.492683 0 0 0-14.823025-2.200351zM539.0336 329.181034l-2.340215 15.764605a7.492683 7.492683 0 1 0 14.820527 2.200351l2.342712-15.764605a7.492683 7.492683 0 0 0-14.823024-2.200351z" fill="#524F75" /><path d="M389.619512 289.717073m-47.453658 0a47.453659 47.453659 0 1 0 94.907317 0 47.453659 47.453659 0 1 0-94.907317 0Z" fill="#FFFFFF" /><path d="M389.619512 344.663415C359.274146 344.663415 334.673171 320.062439 334.673171 289.717073S359.274146 234.770732 389.619512 234.770732s54.946341 24.600976 54.946342 54.946341-24.600976 54.946341-54.946342 54.946342z m0-14.985366c22.068449 0 39.960976-17.892527 39.960976-39.960976S411.687961 249.756098 389.619512 249.756098 349.658537 267.648624 349.658537 289.717073s17.892527 39.960976 39.960975 39.960976z" fill="#524F75" /><path d="M365.787785 302.007571A14.985366 14.985366 0 1 0 362.146341 291.909932l11.109152 1.615922-7.467708 8.481717z" fill="#232323" />
</svg>

          </div>
          <div class="dialog-text">
          <p>Don't worry. We have details explaining how to use each trait effectively, including best practices and common pitfalls.</p>
          </div>
        </div>
<div class="paragraph">
<p>This is where Rust&#8217;s conversion traits come into play. These traits provide standardized ways to convert between types, with clear semantics about cost, fallibility, and ownership. Understanding these traits is crucial for writing idiomatic, flexible Rust code.</p>
</div>
<div class="paragraph">
<p>This article explores the various conversion traits in Rust, explaining:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>When to use each trait</p>
</li>
<li>
<p>How they relate to each other</p>
</li>
<li>
<p>Common pitfalls and best practices</p>
</li>
<li>
<p>Real-world examples of each trait in action</p>
</li>
</ul>
</div>
</div>
</div>
<div class="sect1">
<h2 id="the-conversion-trait-ecosystem">The Conversion Trait Ecosystem</h2>
<div class="sectionbody">
<div class="paragraph">
<p>Before diving into each trait, it&#8217;s helpful to understand how they relate to each other:</p>
</div>
<table class="tableblock frame-all grid-all stretch">
<colgroup>
<col style="width: 25%;">
<col style="width: 25%;">
<col style="width: 25%;">
<col style="width: 25%;">
</colgroup>
<thead>
<tr>
<th class="tableblock halign-left valign-top">Trait Group</th>
<th class="tableblock halign-left valign-top">Infallible</th>
<th class="tableblock halign-left valign-top">Fallible</th>
<th class="tableblock halign-left valign-top">Purpose</th>
</tr>
</thead>
<tbody>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">Value conversion</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>From</code>/<code>Into</code></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>TryFrom</code>/<code>TryInto</code></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Convert between owned values</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">String parsing</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">N/A</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>FromStr</code></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Parse strings into types</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">Reference conversion</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>AsRef</code>/<code>AsMut</code></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">N/A</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Cheap reference-to-reference conversion</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">Reference with semantics</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>Borrow</code>/<code>BorrowMut</code></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">N/A</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Reference conversion preserving equality/hash/ordering</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">Borrowed to owned</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>ToOwned</code></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">N/A</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Get owned values from borrowed data</p></td>
</tr>
</tbody>
</table>
</div>
</div>
<div class="sect1">
<h2 id="from-and-into">From and Into</h2>
<div class="sectionbody">
<div class="sect2">
<h3 id="core-concepts">Core Concepts</h3>
<div class="paragraph">
<p><code>From</code> and <code>Into</code> are the most fundamental conversion traits in Rust. They handle infallible conversions between owned values.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-rust" data-lang="rust">pub trait From&lt;T&gt;: Sized {
    fn from(value: T) -&gt; Self;
}

pub trait Into&lt;T&gt;: Sized {
    fn into(self) -&gt; T;
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>These traits are reciprocal - implementing <code>From</code> automatically gives you <code>Into</code> thanks to a generic blanket implementation:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-rust" data-lang="rust">impl&lt;T, U&gt; Into&lt;U&gt; for T
where
    U: From&lt;T&gt;,
{
    fn into(self) -&gt; U {
        U::from(self)
    }
}</code></pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="key-characteristics">Key Characteristics</h3>
<div class="ulist">
<ul>
<li>
<p><strong>Ownership</strong>: Both traits take ownership of the source value and return an owned value</p>
</li>
<li>
<p><strong>Infallible</strong>: Conversions are expected to always succeed (no <code>Result</code> return type)</p>
</li>
<li>
<p><strong>Costly</strong>: May involve memory allocation and data copying</p>
</li>
<li>
<p><strong>Direction</strong>: Prefer implementing <code>From</code> rather than <code>Into</code> due to the blanket implementation</p>
</li>
</ul>
</div>
</div>
<div class="sect2">
<h3 id="when-to-use-frominto">When to Use From/Into</h3>
<div class="paragraph">
<p>Use <code>From</code> and <code>Into</code> when:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>You need to convert between owned values</p>
</li>
<li>
<p>The conversion cannot fail</p>
</li>
<li>
<p>You prefer a more ergonomic, method-call syntax (for <code>Into</code>)</p>
</li>
</ul>
</div>
</div>
<div class="sect2">
<h3 id="example-point-conversion">Example: Point Conversion</h3>
<div class="paragraph">
<p>Here&#8217;s a practical example showing how to implement <code>From</code> for converting between a tuple and a Point struct:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-rust" data-lang="rust">struct Point {
    x: i32,
    y: i32,
}

// Converting from a tuple to a Point
impl From&lt;(i32, i32)&gt; for Point {
    fn from((x, y): (i32, i32)) -&gt; Self {
        Point { x, y }
    }
}

// Converting from a Point to a tuple
impl From&lt;Point&gt; for (i32, i32) {
    fn from(Point { x, y }: Point) -&gt; Self {
        (x, y)
    }
}

fn example() {
    // Using From
    let p1 = Point::from((10, 20));

    // Using Into
    let p2: Point = (10, 20).into();

    // Converting back to a tuple
    let t1: (i32, i32) = p1.into();
    let t2 = (i32, i32)::from(p2);
}</code></pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="complex-example-triangle-from-points">Complex Example: Triangle from Points</h3>
<div class="paragraph">
<p>This example demonstrates how to compose conversions, allowing a <code>Triangle</code> to be created from anything that can be converted into `Point`s:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-rust" data-lang="rust">struct Triangle {
    p1: Point,
    p2: Point,
    p3: Point,
}

// This implementation allows creating a Triangle from any array of 3 items,
// as long as those items can be converted into Points
impl&lt;P&gt; From&lt;[P; 3]&gt; for Triangle
where
    P: Into&lt;Point&gt;,
{
    fn from([p1, p2, p3]: [P; 3]) -&gt; Self {
        Triangle {
            p1: p1.into(),
            p2: p2.into(),
            p3: p3.into(),
        }
    }
}

fn example() {
    // Create a triangle directly from tuples
    let triangle: Triangle = [(0, 0), (1, 1), (2, 2)].into();

    // Mix and match different types that can convert to Points
    let p1 = Point { x: 0, y: 0 };
    let p2 = (1, 1);
    let p3 = Point { x: 2, y: 2 };
    let triangle = Triangle { p1, p2: p2.into(), p3 };
}</code></pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="best-practices-for-frominto">Best Practices for From/Into</h3>
<div class="olist arabic">
<ol class="arabic">
<li>
<p><strong>Prefer implementing <code>From</code> over <code>Into</code></strong> - You get <code>Into</code> for free, and <code>From</code> impls tend to be more reusable.</p>
</li>
<li>
<p><strong>Reserve for infallible conversions</strong> - If your conversion might fail, use <code>TryFrom</code>/<code>TryInto</code> instead.</p>
</li>
<li>
<p><strong>Be mindful of expensive conversions</strong> - These traits should be used for reasonable cost conversions; extremely expensive operations might warrant a different approach.</p>
</li>
<li>
<p><strong>Follow the "newtype" pattern</strong> - When wrapping a type, always implement <code>From</code> and <code>Into</code> between the wrapper and the wrapped type.</p>
</li>
</ol>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="tryfrom-and-tryinto">TryFrom and TryInto</h2>
<div class="sectionbody">
<div class="sect2">
<h3 id="core-concepts-2">Core Concepts</h3>
<div class="paragraph">
<p><code>TryFrom</code> and <code>TryInto</code> are the fallible versions of <code>From</code> and <code>Into</code>. They return a <code>Result</code> to indicate whether the conversion succeeded or failed.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-rust" data-lang="rust">pub trait TryFrom&lt;T&gt;: Sized {
    type Error;
    fn try_from(value: T) -&gt; Result&lt;Self, Self::Error&gt;;
}

pub trait TryInto&lt;T&gt;: Sized {
    type Error;
    fn try_into(self) -&gt; Result&lt;T, Self::Error&gt;;
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>Just like <code>From</code> and <code>Into</code>, these traits are reciprocal with a blanket implementation:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-rust" data-lang="rust">impl&lt;T, U&gt; TryInto&lt;U&gt; for T
where
    U: TryFrom&lt;T&gt;,
{
    type Error = U::Error;
    fn try_into(self) -&gt; Result&lt;U, Self::Error&gt; {
        U::try_from(self)
    }
}</code></pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="key-characteristics-2">Key Characteristics</h3>
<div class="ulist">
<ul>
<li>
<p><strong>Ownership</strong>: Takes ownership and returns owned values</p>
</li>
<li>
<p><strong>Fallible</strong>: Returns a <code>Result</code> type to handle conversion failures</p>
</li>
<li>
<p><strong>Associated Error Type</strong>: Requires defining the error type for conversion failures</p>
</li>
<li>
<p><strong>Compatibility</strong>: Cannot implement both <code>From&lt;T&gt;</code> and <code>TryFrom&lt;T&gt;</code> for the same type</p>
</li>
</ul>
</div>
</div>
<div class="sect2">
<h3 id="when-to-use-tryfromtryinto">When to Use TryFrom/TryInto</h3>
<div class="paragraph">
<p>Use <code>TryFrom</code> and <code>TryInto</code> when:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>Your conversion might reasonably fail</p>
</li>
<li>
<p>You need to communicate specific error conditions</p>
</li>
<li>
<p>You&#8217;re dealing with input validation or constraints</p>
</li>
</ul>
</div>
</div>
<div class="sect2">
<h3 id="example-bounded-point-conversion">Example: Bounded Point Conversion</h3>
<div class="paragraph">
<p>Let&#8217;s modify our <code>Point</code> example to ensure coordinates fall within a valid range:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-rust" data-lang="rust">use std::convert::TryFrom;
use std::error;
use std::fmt;

struct Point {
    x: i32,
    y: i32,
}

#[derive(Debug)]
struct OutOfBoundsError;

impl fmt::Display for OutOfBoundsError {
    fn fmt(&amp;self, f: &amp;mut fmt::Formatter&lt;'_&gt;) -&gt; fmt::Result {
        write!(f, "point coordinates out of bounds (must be between -1000 and 1000)")
    }
}

impl error::Error for OutOfBoundsError {}

// Now fallible - coordinates must be within range
impl TryFrom&lt;(i32, i32)&gt; for Point {
    type Error = OutOfBoundsError;

    fn try_from((x, y): (i32, i32)) -&gt; Result&lt;Self, Self::Error&gt; {
        if x.abs() &gt; 1000 || y.abs() &gt; 1000 {
            return Err(OutOfBoundsError);
        }
        Ok(Point { x, y })
    }
}

// Still infallible - any Point can be converted to a tuple
impl From&lt;Point&gt; for (i32, i32) {
    fn from(Point { x, y }: Point) -&gt; Self {
        (x, y)
    }
}

fn example() -&gt; Result&lt;(), OutOfBoundsError&gt; {
    // Valid point
    let p1 = Point::try_from((100, 200))?;

    // Using TryInto
    let p2: Result&lt;Point, _&gt; = (100, 200).try_into();

    // Will fail - out of bounds
    let p3 = Point::try_from((2000, 3000))?; // Returns Err

    Ok(())
}</code></pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="complex-example-fallible-triangle-construction">Complex Example: Fallible Triangle Construction</h3>
<div class="paragraph">
<p>Building on our previous example, we can make triangle construction fallible:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-rust" data-lang="rust">struct Triangle {
    p1: Point,
    p2: Point,
    p3: Point,
}

impl&lt;P&gt; TryFrom&lt;[P; 3]&gt; for Triangle
where
    P: TryInto&lt;Point&gt;,
    P::Error: Into&lt;Box&lt;dyn error::Error&gt;&gt;, // Allow flexible error types
{
    type Error = Box&lt;dyn error::Error&gt;;

    fn try_from([p1, p2, p3]: [P; 3]) -&gt; Result&lt;Self, Self::Error&gt; {
        Ok(Triangle {
            p1: p1.try_into().map_err(Into::into)?,
            p2: p2.try_into().map_err(Into::into)?,
            p3: p3.try_into().map_err(Into::into)?,
        })
    }
}

fn create_triangle() -&gt; Result&lt;Triangle, Box&lt;dyn error::Error&gt;&gt; {
    // Will succeed if all points are within bounds
    let t: Triangle = [(0, 0), (100, 100), (200, 200)].try_into()?;

    // Will fail if any point is out of bounds
    let t_fail: Triangle = [(0, 0), (2000, 2000), (200, 200)].try_into()?;

    Ok(t)
}</code></pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="automatic-tryfrom-for-from-types">Automatic TryFrom for From Types</h3>
<div class="paragraph">
<p>It&#8217;s worth noting that types implementing <code>From&lt;T&gt;</code> automatically get a <code>TryFrom&lt;T&gt;</code> implementation:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-rust" data-lang="rust">use std::convert::Infallible;

// This is how the standard library provides it
impl&lt;T, U&gt; TryFrom&lt;U&gt; for T
where
    T: From&lt;U&gt;,
{
    type Error = Infallible; // The empty type that can't be instantiated

    fn try_from(value: U) -&gt; Result&lt;Self, Self::Error&gt; {
        Ok(T::from(value))
    }
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>This means you can always use <code>try_from</code> or <code>try_into</code> even on types that implement <code>From</code>/<code>Into</code>, which can be useful for API consistency.</p>
</div>
</div>
<div class="sect2">
<h3 id="best-practices-for-tryfromtryinto">Best Practices for TryFrom/TryInto</h3>
<div class="olist arabic">
<ol class="arabic">
<li>
<p><strong>Use meaningful error types</strong> - Custom error types help users understand why conversions failed</p>
</li>
<li>
<p><strong>Document failure conditions</strong> - Make it clear when and why conversions might fail</p>
</li>
<li>
<p><strong>Be consistent</strong> - If a type might reasonably have both fallible and infallible conversions, consider sticking with <code>TryFrom</code> for all conversions for consistency</p>
</li>
<li>
<p><strong>Consider validation needs</strong> - Use these traits when input validation is a key part of the conversion process</p>
</li>
</ol>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="fromstr">FromStr</h2>
<div class="sectionbody">
<div class="sect2">
<h3 id="core-concepts-3">Core Concepts</h3>
<div class="paragraph">
<p><code>FromStr</code> is a specialized parsing trait for creating types from string slices. It&#8217;s one of Rust&#8217;s most commonly used traits due to its integration with the <code>.parse()</code> method on strings.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-rust" data-lang="rust">pub trait FromStr: Sized {
    type Err;
    fn from_str(s: &amp;str) -&gt; Result&lt;Self, Self::Err&gt;;
}</code></pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="key-characteristics-3">Key Characteristics</h3>
<div class="ulist">
<ul>
<li>
<p><strong>String-Specific</strong>: Designed specifically for parsing strings</p>
</li>
<li>
<p><strong>Fallible</strong>: Returns a <code>Result</code> to handle parsing failures</p>
</li>
<li>
<p><strong>Integrated</strong>: Works with the <code>.parse()</code> method on string types</p>
</li>
<li>
<p><strong>Read-Only</strong>: Takes a borrowed <code>&amp;str</code> and doesn&#8217;t modify the original</p>
</li>
</ul>
</div>
</div>
<div class="sect2">
<h3 id="when-to-use-fromstr">When to Use FromStr</h3>
<div class="paragraph">
<p>Use <code>FromStr</code> when:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>You need to parse a string into your type</p>
</li>
<li>
<p>The parsing might fail</p>
</li>
<li>
<p>You want to support the standard <code>.parse()</code> method</p>
</li>
</ul>
</div>
</div>
<div class="sect2">
<h3 id="example-parsing-a-point">Example: Parsing a Point</h3>
<div class="paragraph">
<p>Let&#8217;s implement <code>FromStr</code> for our <code>Point</code> type to parse strings like "(10, 20)":</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-rust" data-lang="rust">use std::error;
use std::fmt;
use std::str::FromStr;

struct Point {
    x: i32,
    y: i32,
}

#[derive(Debug, PartialEq)]
struct ParsePointError;

impl fmt::Display for ParsePointError {
    fn fmt(&amp;self, f: &amp;mut fmt::Formatter&lt;'_&gt;) -&gt; fmt::Result {
        write!(f, "failed to parse point - expected format: (x, y)")
    }
}

impl error::Error for ParsePointError {}

impl From&lt;std::num::ParseIntError&gt; for ParsePointError {
    fn from(_: std::num::ParseIntError) -&gt; Self {
        ParsePointError
    }
}

impl FromStr for Point {
    type Err = ParsePointError;

    fn from_str(s: &amp;str) -&gt; Result&lt;Self, Self::Err&gt; {
        // Remove whitespace and check format
        let s = s.trim();
        if !s.starts_with('(') || !s.ends_with(')') {
            return Err(ParsePointError);
        }

        // Extract the content between parentheses
        let inner = &amp;s[1..s.len()-1];
        let mut parts = inner.split(',');

        // Get x and y values
        let x_str = parts.next().ok_or(ParsePointError)?.trim();
        let y_str = parts.next().ok_or(ParsePointError)?.trim();

        // Ensure no extra parts
        if parts.next().is_some() {
            return Err(ParsePointError);
        }

        // Parse into integers
        let x = x_str.parse::&lt;i32&gt;()?;
        let y = y_str.parse::&lt;i32&gt;()?;

        Ok(Point { x, y })
    }
}

fn example() -&gt; Result&lt;(), ParsePointError&gt; {
    // Using from_str directly
    let p1 = Point::from_str("(10, 20)")?;

    // Using parse method (most idiomatic)
    let p2: Point = "(30, 40)".parse()?;

    // Invalid format
    let result = "(not a point)".parse::&lt;Point&gt;();
    assert_eq!(result, Err(ParsePointError));

    Ok(())
}</code></pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="relationship-with-tryfromstr">Relationship with TryFrom&lt;&amp;str&gt;</h3>
<div class="paragraph">
<p><code>FromStr</code> shares a similar signature with <code>TryFrom&lt;&amp;str&gt;</code>. It&#8217;s good practice to implement both when one is present, by having one delegate to the other:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-rust" data-lang="rust">use std::convert::TryFrom;

// Implement TryFrom&lt;&amp;str&gt; by delegating to FromStr
impl TryFrom&lt;&amp;str&gt; for Point {
    type Error = &lt;Point as FromStr&gt;::Err;

    fn try_from(s: &amp;str) -&gt; Result&lt;Self, Self::Error&gt; {
        Point::from_str(s)
    }
}

fn example() {
    // Now we can use both approaches
    let p1: Result&lt;Point, _&gt; = "(10, 20)".parse();
    let p2 = Point::try_from("(10, 20)");
}</code></pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="best-practices-for-fromstr">Best Practices for FromStr</h3>
<div class="olist arabic">
<ol class="arabic">
<li>
<p><strong>Focus on parsing</strong> - The trait is specifically for string parsing, so avoid other side effects</p>
</li>
<li>
<p><strong>Be flexible with formats</strong> - Accept reasonable variations (spaces, capitalization) when possible</p>
</li>
<li>
<p><strong>Provide useful error messages</strong> - Make it clear why parsing failed</p>
</li>
<li>
<p><strong>Include examples in documentation</strong> - Show the exact string formats you accept</p>
</li>
<li>
<p><strong>Implement TryFrom&lt;&amp;str&gt;</strong> - For consistency, also implement <code>TryFrom&lt;&amp;str&gt;</code> by delegating to your <code>FromStr</code> implementation</p>
</li>
</ol>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="asref-and-asmut">AsRef and AsMut</h2>
<div class="sectionbody">
<div class="sect2">
<h3 id="core-concepts-4">Core Concepts</h3>
<div class="paragraph">
<p><code>AsRef</code> and <code>AsMut</code> traits provide cheap reference-to-reference conversions. They&#8217;re primarily used for making functions more flexible about the types they accept.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-rust" data-lang="rust">pub trait AsRef&lt;T: ?Sized&gt; {
    fn as_ref(&amp;self) -&gt; &amp;T;
}

pub trait AsMut&lt;T: ?Sized&gt; {
    fn as_mut(&amp;mut self) -&gt; &amp;mut T;
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>The <code>?Sized</code> bound allows these traits to be implemented for unsized types like slices.</p>
</div>
</div>
<div class="sect2">
<h3 id="key-characteristics-4">Key Characteristics</h3>
<div class="ulist">
<ul>
<li>
<p><strong>References Only</strong>: Convert between reference types, not owned values</p>
</li>
<li>
<p><strong>Cheap</strong>: Conversions should be inexpensive, often just a cast</p>
</li>
<li>
<p><strong>Read/Write</strong>: <code>AsRef</code> provides read-only access, while <code>AsMut</code> allows modification</p>
</li>
<li>
<p><strong>Type-Based</strong>: Multiple implementations may exist for a single type, differing by the target type</p>
</li>
</ul>
</div>
</div>
<div class="sect2">
<h3 id="when-to-use-asrefasmut">When to Use AsRef/AsMut</h3>
<div class="paragraph">
<p>Use <code>AsRef</code> and <code>AsMut</code> when:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>You want to abstract over similar types, like <code>String</code> and <code>&amp;str</code></p>
</li>
<li>
<p>You need flexible APIs that accept multiple types</p>
</li>
<li>
<p>You&#8217;re exposing an inner reference to a wrapped type</p>
</li>
<li>
<p>You need to convert between reference types cheaply</p>
</li>
</ul>
</div>
</div>
<div class="sect2">
<h3 id="example-flexible-string-functions">Example: Flexible String Functions</h3>
<div class="paragraph">
<p>A common use case is to write functions that accept either <code>String</code> or <code>&amp;str</code>:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-rust" data-lang="rust">// This function accepts both String and &amp;str
fn calculate_length&lt;S: AsRef&lt;str&gt;&gt;(s: S) -&gt; usize {
    s.as_ref().len()
}

fn example() {
    let owned = String::from("hello");
    let borrowed = "world";

    // Both work!
    println!("Length: {}", calculate_length(&amp;owned));
    println!("Length: {}", calculate_length(borrowed));
    println!("Length: {}", calculate_length(owned));  // Takes ownership
}</code></pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="example-exposing-inner-references">Example: Exposing Inner References</h3>
<div class="paragraph">
<p><code>AsRef</code> is valuable when you have a wrapper type and want to provide access to its inner data:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-rust" data-lang="rust">struct EmailAddress {
    address: String,  // Private field with invariants
}

impl EmailAddress {
    fn new(address: String) -&gt; Option&lt;Self&gt; {
        // Validate email format
        if is_valid_email(&amp;address) {
            Some(EmailAddress { address })
        } else {
            None
        }
    }
}

// Allow accessing the inner string as a str
impl AsRef&lt;str&gt; for EmailAddress {
    fn as_ref(&amp;self) -&gt; &amp;str {
        &amp;self.address
    }
}

fn is_valid_email(s: &amp;str) -&gt; bool {
    // Implementation omitted
    s.contains('@')
}

fn example() {
    let email = EmailAddress::new(String::from("user@example.com")).unwrap();

    // We can use it with any function accepting AsRef&lt;str&gt;
    let length = calculate_length(&amp;email);

    // We can get the &amp;str directly
    let domain = email.as_ref().split('@').nth(1).unwrap();
}</code></pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="the-is-a-relationship">The "IS-A" Relationship</h3>
<div class="paragraph">
<p><code>AsRef</code> is often used to express an "IS-A" relationship between types. When you have a type that can conceptually be treated as another type, <code>AsRef</code> makes this relationship explicit:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-rust" data-lang="rust">struct Human {
    health_points: u32,
}

// A Soldier IS-A Human with a weapon
struct Soldier {
    human: Human,
    weapon: String,
}

impl AsRef&lt;Human&gt; for Soldier {
    fn as_ref(&amp;self) -&gt; &amp;Human {
        &amp;self.human
    }
}

// A Knight IS-A Soldier with armor
struct Knight {
    soldier: Soldier,
    armor: String,
}

impl AsRef&lt;Soldier&gt; for Knight {
    fn as_ref(&amp;self) -&gt; &amp;Soldier {
        &amp;self.soldier
    }
}

// Knights can also be treated as Humans directly
impl AsRef&lt;Human&gt; for Knight {
    fn as_ref(&amp;self) -&gt; &amp;Human {
        &amp;self.soldier.human
    }
}

// Generic function that works with any Human-like type
fn heal&lt;T: AsRef&lt;Human&gt;&gt;(entity: &amp;T, amount: u32) {
    println!("Healing for {} points", amount);
    // In a real implementation, we would modify health_points here
}

fn example() {
    let human = Human { health_points: 100 };
    let soldier = Soldier { human: Human { health_points: 120 }, weapon: "Sword".into() };
    let knight = Knight {
        soldier: Soldier { human: Human { health_points: 150 }, weapon: "Lance".into() },
        armor: "Plate".into(),
    };

    // All these work because of our AsRef implementations
    heal(&amp;human, 10);
    heal(&amp;soldier, 10);
    heal(&amp;knight, 10);
}</code></pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="when-not-to-use-asref">When Not to Use AsRef</h3>
<div class="paragraph">
<p><code>AsRef</code> is sometimes overused or used incorrectly. Here are some anti-patterns to avoid:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-rust" data-lang="rust">struct User {
    name: String,
    email: String,
    age: u32,
}

// INCORRECT: Using AsRef to extract fields
impl AsRef&lt;String&gt; for User {
    fn as_ref(&amp;self) -&gt; &amp;String {
        // Which field should we return? Not clear!
        &amp;self.name
    }
}

// INCORRECT: Using AsRef for unrelated types
impl AsRef&lt;u32&gt; for User {
    fn as_ref(&amp;self) -&gt; &amp;u32 {
        &amp;self.age
    }
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>These implementations are problematic because:</p>
</div>
<div class="olist arabic">
<ol class="arabic">
<li>
<p>They don&#8217;t represent true "IS-A" relationships</p>
</li>
<li>
<p>They create ambiguity (which string field does <code>as_ref</code> return?)</p>
</li>
<li>
<p>They lead to unintuitive behavior</p>
</li>
</ol>
</div>
</div>
<div class="sect2">
<h3 id="best-practices-for-asrefasmut">Best Practices for AsRef/AsMut</h3>
<div class="olist arabic">
<ol class="arabic">
<li>
<p><strong>Use for "IS-A" relationships</strong> - Implement when one type can be viewed as another</p>
</li>
<li>
<p><strong>Keep conversions cheap</strong> - Avoid expensive computations in <code>as_ref</code>/<code>as_mut</code></p>
</li>
<li>
<p><strong>Be consistent</strong> - If implementing <code>AsRef&lt;T&gt;</code>, consider implementing <code>AsMut&lt;T&gt;</code> if mutability makes sense</p>
</li>
<li>
<p><strong>Don&#8217;t overuse</strong> - Not every field deserves an <code>AsRef</code> implementation</p>
</li>
<li>
<p><strong>Respect semantics</strong> - Don&#8217;t implement for conceptually unrelated types</p>
</li>
</ol>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="borrow-and-borrowmut">Borrow and BorrowMut</h2>
<div class="sectionbody">
<div class="sect2">
<h3 id="core-concepts-5">Core Concepts</h3>
<div class="paragraph">
<p><code>Borrow</code> and <code>BorrowMut</code> are similar to <code>AsRef</code> and <code>AsMut</code> but with an additional semantic guarantee: the borrowed and borrowing types must behave equivalently with regard to equality, hashing, and ordering.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-rust" data-lang="rust">pub trait Borrow&lt;Borrowed: ?Sized&gt; {
    fn borrow(&amp;self) -&gt; &amp;Borrowed;
}

pub trait BorrowMut&lt;Borrowed: ?Sized&gt;: Borrow&lt;Borrowed&gt; {
    fn borrow_mut(&amp;mut self) -&gt; &amp;mut Borrowed;
}</code></pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="key-characteristics-5">Key Characteristics</h3>
<div class="ulist">
<ul>
<li>
<p><strong>Stricter Than AsRef</strong>: Requires equivalent behavior for hashing and comparisons</p>
</li>
<li>
<p><strong>References Only</strong>: Converts references, not owned values</p>
</li>
<li>
<p><strong>Semantic Guarantee</strong>: Must preserve equality, hash, and ordering properties</p>
</li>
<li>
<p><strong>Collections Focus</strong>: Primarily used in hash and tree-based collections</p>
</li>
</ul>
</div>
</div>
<div class="sect2">
<h3 id="when-to-use-borrowborrowmut">When to Use Borrow/BorrowMut</h3>
<div class="paragraph">
<p>Use <code>Borrow</code> and <code>BorrowMut</code> when:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>You need to lookup objects in collections using different but equivalent types</p>
</li>
<li>
<p>You&#8217;re implementing a hash-based or tree-based collection</p>
</li>
<li>
<p>You need to guarantee that borrowed and owned versions behave identically for comparisons</p>
</li>
</ul>
</div>
</div>
<div class="sect2">
<h3 id="the-hashmaphashset-use-case">The HashMap/HashSet Use Case</h3>
<div class="paragraph">
<p>The most common use case for <code>Borrow</code> is in hash maps and sets, allowing lookups with borrowed versions of keys:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-rust" data-lang="rust">use std::collections::HashMap;
use std::borrow::Borrow;
use std::hash::Hash;

fn example() {
    let mut map: HashMap&lt;String, i32&gt; = HashMap::new();

    // Insert with owned String keys
    map.insert(String::from("apple"), 1);
    map.insert(String::from("banana"), 2);
    map.insert(String::from("cherry"), 3);

    // Lookup with &amp;str - works because String: Borrow&lt;str&gt;
    let apple_value = map.get("apple");
    assert_eq!(apple_value, Some(&amp;1));

    // How does this work? Because HashMap's get method is defined like:
    // fn get&lt;Q: ?Sized&gt;(&amp;self, k: &amp;Q) -&gt; Option&lt;&amp;V&gt;
    // where K: Borrow&lt;Q&gt;, Q: Hash + Eq
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>This works because the standard library implements <code>Borrow&lt;str&gt;</code> for <code>String</code>, ensuring that a <code>String</code> and its borrowed <code>&amp;str</code> form have the same hash value and equality behavior.</p>
</div>
</div>
<div class="sect2">
<h3 id="visualizing-the-difference-between-asref-and-borrow">Visualizing the Difference between AsRef and Borrow</h3>
<div class="paragraph">
<p>Here&#8217;s an example that demonstrates the semantic difference between <code>AsRef</code> and <code>Borrow</code>:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-rust" data-lang="rust">use std::borrow::Borrow;
use std::hash::{Hash, Hasher};
use std::collections::hash_map::DefaultHasher;

// Calculate the hash of a value
fn get_hash&lt;T: Hash&gt;(t: &amp;T) -&gt; u64 {
    let mut hasher = DefaultHasher::new();
    t.hash(&amp;mut hasher);
    hasher.finish()
}

// This type has different hash/eq behavior for different views
struct CustomString {
    data: String,
}

impl Hash for CustomString {
    fn hash&lt;H: Hasher&gt;(&amp;self, state: &amp;mut H) {
        // Custom hash implementation that differs from str's hash
        self.data.len().hash(state);
    }
}

impl PartialEq for CustomString {
    fn eq(&amp;self, other: &amp;Self) -&gt; bool {
        self.data.len() == other.data.len()
    }
}

impl Eq for CustomString {}

// AsRef implementation - just returns a reference
impl AsRef&lt;str&gt; for CustomString {
    fn as_ref(&amp;self) -&gt; &amp;str {
        &amp;self.data
    }
}

// We CANNOT implement Borrow&lt;str&gt; because it would violate
// the semantic requirements - CustomString and str have
// different hash and equality behavior

fn example() {
    let s1 = CustomString { data: String::from("hello") };
    let s2 = CustomString { data: String::from("world") };

    // AsRef works fine
    let r1: &amp;str = s1.as_ref();
    let r2: &amp;str = s2.as_ref();

    // But hash values differ between CustomString and &amp;str
    println!("CustomString hash: {}", get_hash(&amp;s1));
    println!("str hash: {}", get_hash(&amp;r1));

    // And equality behavior differs too
    println!("Same length, equal as CustomString: {}", s1 == CustomString { data: "hello2".into() });
    println!("Different content, not equal as str: {}", r1 == "hello2");

    // This is why we shouldn't implement Borrow&lt;str&gt; for CustomString
}</code></pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="best-practices-for-borrowborrowmut">Best Practices for Borrow/BorrowMut</h3>
<div class="olist arabic">
<ol class="arabic">
<li>
<p><strong>Respect the semantic contract</strong> - Only implement <code>Borrow</code> if the borrowed type behaves identically for hash, eq, and ord operations</p>
</li>
<li>
<p><strong>Use for collection lookups</strong> - The primary use case is enabling flexible lookups in hash and tree collections</p>
</li>
<li>
<p><strong>Consider alternatives</strong> - If you don&#8217;t need the semantic guarantees, <code>AsRef</code> is usually sufficient</p>
</li>
<li>
<p><strong>Delegate to standard impls</strong> - For custom wrapper types, delegate to the inner type&#8217;s implementation</p>
</li>
</ol>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="toowned">ToOwned</h2>
<div class="sectionbody">
<div class="sect2">
<h3 id="core-concepts-6">Core Concepts</h3>
<div class="paragraph">
<p><code>ToOwned</code> generalizes the concept of cloning for borrowed types, allowing creation of owned values from arbitrary borrowed data.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-rust" data-lang="rust">pub trait ToOwned {
    type Owned: Borrow&lt;Self&gt;;
    fn to_owned(&amp;self) -&gt; Self::Owned;

    // Provided default implementation
    fn clone_into(&amp;self, target: &amp;mut Self::Owned) { ... }
}</code></pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="key-characteristics-6">Key Characteristics</h3>
<div class="ulist">
<ul>
<li>
<p><strong>Generalized Clone</strong>: Similar to <code>Clone</code>, but for borrowed-to-owned conversions</p>
</li>
<li>
<p><strong>Associated Type</strong>: Specifies the owned type for a borrowed type</p>
</li>
<li>
<p><strong>Reverse of Borrow</strong>: If <code>T: Borrow&lt;U&gt;</code>, then <code>U: ToOwned&lt;Owned=T&gt;</code></p>
</li>
<li>
<p><strong>Standard Library Use</strong>: Used for common pairs like <code>str</code>/<code>String</code>, <code>Path</code>/<code>PathBuf</code></p>
</li>
</ul>
</div>
</div>
<div class="sect2">
<h3 id="when-to-use-toowned">When to Use ToOwned</h3>
<div class="paragraph">
<p>Use <code>ToOwned</code> when:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>You need to convert borrowed types to owned types</p>
</li>
<li>
<p>You&#8217;re implementing a data structure that can exist in both borrowed and owned forms</p>
</li>
<li>
<p>You need more flexibility than the standard <code>Clone</code> trait</p>
</li>
</ul>
</div>
</div>
<div class="sect2">
<h3 id="common-toowned-implementations">Common ToOwned Implementations</h3>
<div class="paragraph">
<p>The standard library implements <code>ToOwned</code> for several common types:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-rust" data-lang="rust">// str -&gt; String
impl ToOwned for str {
    type Owned = String;
    fn to_owned(&amp;self) -&gt; String {
        String::from(self)
    }
}

// [T] -&gt; Vec&lt;T&gt;
impl&lt;T: Clone&gt; ToOwned for [T] {
    type Owned = Vec&lt;T&gt;;
    fn to_owned(&amp;self) -&gt; Vec&lt;T&gt; {
        self.to_vec()
    }
}

// Path -&gt; PathBuf
impl ToOwned for Path {
    type Owned = PathBuf;
    fn to_owned(&amp;self) -&gt; PathBuf {
        self.to_path_buf()
    }
}</code></pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="example-custom-toowned-implementation">Example: Custom ToOwned Implementation</h3>
<div class="paragraph">
<p>Let&#8217;s create a pair of types with a <code>ToOwned</code> relationship:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-rust" data-lang="rust">use std::borrow::Borrow;
use std::borrow::ToOwned;

#[derive(Debug)]
struct Name {
    first: String,
    last: String,
}

#[derive(Debug)]
struct NameRef&lt;'a&gt; {
    first: &amp;'a str,
    last: &amp;'a str,
}

// Name can be borrowed as NameRef
impl&lt;'a&gt; Borrow&lt;NameRef&lt;'a&gt;&gt; for Name {
    fn borrow(&amp;self) -&gt; &amp;NameRef&lt;'a&gt; {
        // Safety: This is safe because the lifetimes are guaranteed
        // to match and the representation is compatible.
        // In real code, you'd likely implement this differently.
        unsafe {
            &amp;*(self as *const Name as *const NameRef&lt;'a&gt;)
        }
    }
}

// NameRef can be converted to owned Name
impl&lt;'a&gt; ToOwned for NameRef&lt;'a&gt; {
    type Owned = Name;

    fn to_owned(&amp;self) -&gt; Name {
        Name {
            first: self.first.to_owned(),
            last: self.last.to_owned(),
        }
    }
}

fn example() {
    // Create a borrowed version
    let name_ref = NameRef {
        first: "John",
        last: "Doe",
    };

    // Convert to owned using ToOwned
    let owned_name = name_ref.to_owned();

    println!("Borrowed: {:?}", name_ref);
    println!("Owned: {:?}", owned_name);
}</code></pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="best-practices-for-toowned">Best Practices for ToOwned</h3>
<div class="olist arabic">
<ol class="arabic">
<li>
<p><strong>Implement with Borrow</strong> - <code>ToOwned</code> and <code>Borrow</code> should be implemented as pairs</p>
</li>
<li>
<p><strong>Consider performance</strong> - The <code>to_owned</code> method will likely allocate memory, so document performance characteristics</p>
</li>
<li>
<p><strong>Use for borrowed/owned pairs</strong> - This trait is most appropriate when you have distinct borrowed and owned types</p>
</li>
<li>
<p><strong>Provide clone_into when beneficial</strong> - Override the default implementation when you can implement it more efficiently</p>
</li>
</ol>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="conversion-traits-in-practice">Conversion Traits in Practice</h2>
<div class="sectionbody">
<div class="paragraph">
<p>Now that we&#8217;ve covered each conversion trait individually, let&#8217;s explore some practical patterns and considerations for using them effectively.</p>
</div>
<div class="sect2">
<h3 id="choosing-the-right-trait">Choosing the Right Trait</h3>
<div class="paragraph">
<p>To select the appropriate conversion trait, consider these questions:</p>
</div>
<div class="olist arabic">
<ol class="arabic">
<li>
<p><strong>Is the conversion fallible?</strong></p>
<div class="ulist">
<ul>
<li>
<p>Yes → <code>TryFrom</code>/<code>TryInto</code> or <code>FromStr</code> (for strings)</p>
</li>
<li>
<p>No → <code>From</code>/<code>Into</code></p>
</li>
</ul>
</div>
</li>
<li>
<p><strong>Are you converting between references or values?</strong></p>
<div class="ulist">
<ul>
<li>
<p>References → <code>AsRef</code>/<code>AsMut</code> or <code>Borrow</code>/<code>BorrowMut</code></p>
</li>
<li>
<p>Values → <code>From</code>/<code>Into</code> or <code>TryFrom</code>/<code>TryInto</code></p>
</li>
</ul>
</div>
</li>
<li>
<p><strong>Do you need to preserve hash/equality behavior?</strong></p>
<div class="ulist">
<ul>
<li>
<p>Yes → <code>Borrow</code>/<code>BorrowMut</code></p>
</li>
<li>
<p>No → <code>AsRef</code>/<code>AsMut</code></p>
</li>
</ul>
</div>
</li>
<li>
<p><strong>Are you creating an owned value from a borrowed one?</strong></p>
<div class="ulist">
<ul>
<li>
<p>Yes → <code>ToOwned</code></p>
</li>
<li>
<p>No → Other traits</p>
</li>
</ul>
</div>
</li>
</ol>
</div>
</div>
<div class="sect2">
<h3 id="composing-conversions">Composing Conversions</h3>
<div class="paragraph">
<p>Rust&#8217;s conversion traits work well together, allowing you to build flexible and composable APIs:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-rust" data-lang="rust">// A function that accepts anything convertible to a Point
fn distance_from_origin&lt;P&gt;(point: P) -&gt; f64
where
    P: Into&lt;Point&gt;,
{
    let point = point.into();
    ((point.x.pow(2) + point.y.pow(2)) as f64).sqrt()
}

// A function that accepts anything convertible to a &amp;str
fn find_pattern&lt;S: AsRef&lt;str&gt;&gt;(text: S, pattern: S) -&gt; bool {
    text.as_ref().contains(pattern.as_ref())
}

// A function that tries to parse a value from a string-like input
fn parse_value&lt;S, T&gt;(input: S) -&gt; Result&lt;T, T::Err&gt;
where
    S: AsRef&lt;str&gt;,
    T: FromStr,
{
    input.as_ref().parse::&lt;T&gt;()
}</code></pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="generic-api-design-pattern">Generic API Design Pattern</h3>
<div class="paragraph">
<p>One powerful pattern is to design APIs that accept the most general form of input:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-rust" data-lang="rust">struct Config {
    database_url: String,
    port: u16,
    allowed_origins: Vec&lt;String&gt;,
    // other fields...
}

impl Config {
    // This constructor accepts flexible inputs for all string fields
    pub fn new&lt;S1, S2, I&gt;(database_url: S1, port: u16, origins: I) -&gt; Self
    where
        S1: Into&lt;String&gt;,
        S2: Into&lt;String&gt;,
        I: IntoIterator&lt;Item = S2&gt;,
    {
        Config {
            database_url: database_url.into(),
            port,
            allowed_origins: origins.into_iter().map(Into::into).collect(),
        }
    }
}

fn example() {
    // Works with various combinations of strings
    let config = Config::new(
        "postgres://localhost/db",  // &amp;str
        8080,
        vec!["http://localhost:3000", String::from("https://example.com")]
    );
}</code></pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="common-pitfalls-and-solutions">Common Pitfalls and Solutions</h3>
<div class="sect3">
<h4 id="1-trait-bounds-too-restrictive">1. Trait Bounds Too Restrictive</h4>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-rust" data-lang="rust">// Too restrictive - requires exactly String
fn bad_function(s: String) {
    // ...
}

// Better - accepts anything convertible to String
fn better_function&lt;S: Into&lt;String&gt;&gt;(s: S) {
    let s = s.into();
    // ...
}

// Also good - doesn't take ownership if not needed
fn best_function&lt;S: AsRef&lt;str&gt;&gt;(s: S) {
    let s = s.as_ref();
    // ...
}</code></pre>
</div>
</div>
</div>
<div class="sect3">
<h4 id="2-unnecessary-conversions">2. Unnecessary Conversions</h4>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-rust" data-lang="rust">// Inefficient - converts to String when &amp;str would work
fn tokenize&lt;S: Into&lt;String&gt;&gt;(s: S) -&gt; Vec&lt;String&gt; {
    let s = s.into();  // Potentially unnecessary allocation
    s.split_whitespace().map(|s| s.to_string()).collect()
}

// Better - uses AsRef to avoid unnecessary conversion
fn tokenize_better&lt;S: AsRef&lt;str&gt;&gt;(s: S) -&gt; Vec&lt;String&gt; {
    s.as_ref().split_whitespace().map(|s| s.to_string()).collect()
}</code></pre>
</div>
</div>
</div>
<div class="sect3">
<h4 id="3-missing-error-context">3. Missing Error Context</h4>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-rust" data-lang="rust">// Loses context about which field failed
fn parse_config&lt;S: AsRef&lt;str&gt;&gt;(
    name: S,
    value: S,
) -&gt; Result&lt;Config, ParseError&gt; {
    let name = name.as_ref();
    let value = value.as_ref();

    let port: u16 = value.parse()?;  // Which field caused this error?
    let timeout: u64 = value.parse()?;

    // ...
}

// Better - preserves context
enum FieldError {
    Port(std::num::ParseIntError),
    Timeout(std::num::ParseIntError),
    // ...
}

fn parse_config_better&lt;S: AsRef&lt;str&gt;&gt;(
    name: S,
    value: S,
) -&gt; Result&lt;Config, FieldError&gt; {
    let name = name.as_ref();
    let value = value.as_ref();

    let port: u16 = value.parse().map_err(FieldError::Port)?;
    let timeout: u64 = value.parse().map_err(FieldError::Timeout)?;

    // ...
}</code></pre>
</div>
</div>
</div>
</div>
<div class="sect2">
<h3 id="trait-coherence-and-the-orphan-rule">Trait Coherence and the Orphan Rule</h3>
<div class="paragraph">
<p>When working with conversion traits, you&#8217;ll encounter Rust&#8217;s "orphan rule," which prevents you from implementing external traits for external types. This affects how you can implement conversion traits:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-rust" data-lang="rust">// OK: Implementing From&lt;MyType&gt; for std::path::PathBuf
struct MyType(String);
impl From&lt;MyType&gt; for std::path::PathBuf {
    fn from(mt: MyType) -&gt; Self {
        PathBuf::from(mt.0)
    }
}

// ERROR: Cannot implement std::convert::From&lt;std::path::PathBuf&gt; for MyType
// because both types are defined outside your crate
impl From&lt;std::path::PathBuf&gt; for MyType {
    fn from(path: std::path::PathBuf) -&gt; Self {
        MyType(path.to_string_lossy().into_owned())
    }
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>Workarounds for the orphan rule:</p>
</div>
<div class="olist arabic">
<ol class="arabic">
<li>
<p><strong>Use a newtype wrapper</strong> - Wrap the external type in your own type</p>
</li>
<li>
<p><strong>Use extension traits</strong> - Create your own trait that extends the functionality</p>
</li>
<li>
<p><strong>Use TryFrom instead of From</strong> - Sometimes this can avoid coherence issues due to different associated types</p>
</li>
</ol>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="conclusion">Conclusion</h2>
<div class="sectionbody">
<div class="paragraph">
<p>Rust&#8217;s conversion traits provide a rich, flexible system for handling type conversions in a way that&#8217;s both safe and expressive. By understanding the distinctions between these traits and their intended use cases, you can design APIs that are both ergonomic and idiomatic.</p>
</div>
<div class="paragraph">
<p>Key takeaways:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>Use <code>From</code>/<code>Into</code> for infallible value conversions</p>
</li>
<li>
<p>Use <code>TryFrom</code>/<code>TryInto</code> for fallible value conversions</p>
</li>
<li>
<p>Use <code>FromStr</code> for parsing from string representations</p>
</li>
<li>
<p>Use <code>AsRef</code>/<code>AsMut</code> for cheap reference conversions</p>
</li>
<li>
<p>Use <code>Borrow</code>/<code>BorrowMut</code> when hash and equality semantics matter</p>
</li>
<li>
<p>Use <code>ToOwned</code> for borrowed-to-owned conversions</p>
</li>
</ul>
</div>
<div class="paragraph">
<p>These traits form the backbone of Rust&#8217;s approach to interoperability between different types, enabling code that is both flexible and type-safe. By following the patterns and best practices outlined in this article, you&#8217;ll be able to leverage these traits effectively in your own Rust programs.</p>
</div>
</div>
</div>]]></content><author><name>ohmycloud</name></author><summary type="html"><![CDATA[Introduction]]></summary></entry><entry><title type="html">Authentication with Axum</title><link href="https://ohmycloud.github.io/2025/05/03/authentication-with-axum.html" rel="alternate" type="text/html" title="Authentication with Axum" /><published>2025-05-03T00:00:00+00:00</published><updated>2025-05-03T00:00:00+00:00</updated><id>https://ohmycloud.github.io/2025/05/03/authentication-with-axum</id><content type="html" xml:base="https://ohmycloud.github.io/2025/05/03/authentication-with-axum.html"><![CDATA[<div class="paragraph">
<p>Consider this scenario: you&#8217;re building a website that has a classic navbar at
the top, this navbar has a button that reflects the user authentication status,
showing a "Profile" button if the user is authenticated and showing a
"Login" button in case the user is unauthenticated.</p>
</div>
<div class="paragraph">
<p>This is a very common scenario, let&#8217;s sketch something quick using axum and
askama.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-html" data-lang="html">&lt;!DOCTYPE html&gt;
&lt;html lang="en"&gt;

&lt;head&gt;
    &lt;title&gt;{% block title %}{% endblock %}&lt;/title&gt;
    &lt;meta charset="UTF-8" /&gt;
    &lt;meta name="viewport" content="width=device-width, initial-scale=1.0" /&gt;
    {% block head %}{% endblock %}
&lt;/head&gt;
&lt;body&gt;
    &lt;nav&gt;
        &lt;div&gt;
            &lt;div&gt;
                {% if ctx.authed %}
                    &lt;a href="/profile"&gt;Profile&lt;/a&gt;
                {% else %}
                    &lt;a href="/login"&gt;Login&lt;/a&gt;
                {% endif %}
            &lt;/div&gt;
        &lt;/div&gt;
    &lt;/nav&gt;
    {% block content %}
    {% endblock %}
&lt;/body&gt;
&lt;/html&gt;</code></pre>
</div>
</div>
<div class="paragraph">
<p>This will be our <code>layout.jinja</code> file that we can build upon. The template above
would be served by an endpoint that looks like the following</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-rust" data-lang="rust">#[derive(Debug, Default)]
pub struct Context {
    authed: bool,
}

#[derive(Template)]
#[templage = "layout.jinja"]
struct HomeTemplate {
    ctx: Context
};

pub async fn home() -&gt; impl IntoResponse {
    HtmlTemplate(
        HomeTemplate { ctx: Context::default() }
    ).into_response()
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>We have something to work with, all is missing is a way derive a
<code>Context</code> from a user&#8217;s HTTP request.</p>
</div>
<div class="paragraph">
<p>I&#8217;d argue the simplest way to handle user authentication if you&#8217;re doing SSR is
using cookies. Cookies are a cornerstone of backend authentication because
they’re reliable, browser-managed, and can be hardened with specific attributes
to mitigate common security risks. Here’s why:</p>
</div>
<div class="ulist">
<ul>
<li>
<p><code>HttpOnly</code> Attribute: Prevents client-side JavaScript from accessing the
cookie, neutralizing XSS attacks. If an attacker injects malicious scripts,
they can’t steal your session cookie.</p>
</li>
<li>
<p><code>Secure</code> Attribute: Ensures the cookie is only sent over HTTPS, protecting it
from interception on insecure networks (e.g., public Wi-Fi).</p>
</li>
<li>
<p><code>SameSite</code> Attribute: Mitigates CSRF (Cross-Site Request Forgery) by
controlling when cookies are sent in cross-origin requests. SameSite=Strict
blocks cookies in requests from external sites, while SameSite=Lax allows
safe methods like GET.</p>
</li>
<li>
<p>Expiration and Domain/Path Scoping: Cookies can be set to expire after a
session or a fixed time, reducing the window for misuse. Scoping to specific
domains and paths (e.g., <code>domain=api.example.com</code>, <code>path=/auth</code>) limits their
exposure.</p>
</li>
<li>
<p>Signed Cookies: Frameworks often support signing cookies with a secret key,
ensuring they haven’t been tampered with on the client side.</p>
</li>
</ul>
</div>
<div class="paragraph">
<p>This is a typical reponse that uses the <code>Set-Cookies</code> header to instruct the
browser to set those cookies</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-http" data-lang="http">HTTP/1.1 200 OK
Content-Type: application/json
Set-Cookie: session=xyz123; HttpOnly; Secure; SameSite=Strict; Max-Age=86400; Path=/; Domain=api.example.com</code></pre>
</div>
</div>
<div class="paragraph">
<p>When configured correctly, cookies are a fortress for storing session IDs,
JWTs, or other authentication tokens in SSR apps. They’re automatically
sent by the browser with every request, simplifying server-side validation
compared to managing tokens in <code>localStorage</code> or HTTP headers.</p>
</div>
<div class="paragraph">
<p>Axum provides a cool <a href="https://docs.rs/axum-extra/0.10.1/axum_extra"><code>axum-extra</code></a> crate that makes it easy to
work with them. That crate contains a very useful extractor called <code>CookieJar</code>
that exposes a very minimal interface to <code>.add</code> and <code>.remove</code> cookies for a
user. This is the utility function I use to generate a default cookie</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-rust" data-lang="rust">pub(crate) fn default_cookie&lt;'a&gt;(
    key: &amp;str,
    token: String,
    duration_hrs: i64
) -&gt; Cookie&lt;'a&gt; {
    Cookie::build((key.to_string(), token))
        .path("/")
        .http_only(true)
        .max_age(Duration::hours(duration_hrs))
        .secure(if cfg!(debug_assertions) {
            // Safari won't allow secure cookies
            // coming from localhost in debug mode
            false
        } else {
            // Secure cookies in release mode
            true
        })
        .build()
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>I won’t get sucked into the session ID vs. JWT argument, but honestly, using
JWTs in cookies is a win because you don’t have to fuss with storing session
data on the server.</p>
</div>
<div class="paragraph">
<p>Jwt are usually very short-lived, they shouldn&#8217;t last for long periods of time
and they must be renewed frequently for security purposes. For that reason you
usually issue two different cookies:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>jwt: short-lived token containing information about a user in json format,
signed with a secret key so you know you were the one who issued it</p>
</li>
<li>
<p>refresh token: a longer-lived token with which you can request new jwts</p>
</li>
</ul>
</div>
<div class="paragraph">
<p>Now that we&#8217;ve covered the cookies and jwt basics, let&#8217;s start by implementing
a standard login endpoint with which users can be given these two cookies.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-rust" data-lang="rust">#[derive(Debug)]
struct LoginData {
    username: String,
    password: String
}

pub async fn login(
    State(app): State&lt;AppState&gt;,
    jar: CookieJar, // CookieJar is available in axum_extras
    Form(LoginData { username, password }): Form&lt;LoginData&gt;
) -&gt; impl IntoResponse {
    // dummy function to get a user
    let user = match db::user::get(&amp;app.pg_pool, &amp;username, &amp;password).await {
        None =&gt; return Redirect::to("/signup").into_response()
        Some(user) =&gt; user
    };

    // get/create a refresh token for the user
    let refresh_token = match db::refresh_tokens::create(user.id).await {
        Ok(token) =&gt; token,
        Err(_) =&gt; {
            return (
                StatusCode::INTERNAL_SERVER_ERROR,
                "Somethign bad happened, try again later"
            ).into_response();
        }
    };

    let claims = Claims::with(user.email, user.id);
    match jwt::generate_jwt(app.jwt_signing_key.as_bytes(), claims) {
        Ok(token) =&gt; (
            [("hx-redirect", "/")],
            jar.add(default_cookie("jwt", token, 1)).add(default_cookie(
                "refresh",
                refresh_token,
                30 * 24,
            ),
        )
            .into_response()),
        Err(_) =&gt; {
            return (
                StatusCode::INTERNAL_SERVER_ERROR,
                "Somethign bad happened, try again later"
            ).into_response();
        }
    }
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>This login endpoint will receive a request with some form data that contain a
<code>username</code> and a <code>password</code>. First thing you usually have to do is check if the
user exists in your database, otherwise you&#8217;ll kindly <code>302</code> to a signup page
where he/she has to register, returning a message to show in the login form
sometimes works as well - whatever suits you.</p>
</div>
<div class="paragraph">
<p>Once you know the user exists you need to create a refresh token. It usually
makes sense to implement <code>refresh_token::create</code> so that it returns a valid
non-expired refresh token stored in your database associated with the user
before creating a new one. This is because users can delete cookies and/or
users can authenticate with different devices and you don&#8217;t want to create a
refresh token each time.</p>
</div>
<div class="paragraph">
<p>When you get your refresh token back you&#8217;re ready to move on and handle the
last part of the process, which is generating the jwt and returning a valid
response to the user that will set those cookies.</p>
</div>
        <div class="dialog matt" title="Matt">
          <div class="dialog-head" aria-hidden="true">
          <?xml version="1.0" encoding="utf-8"?>
<!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
<svg width="800px" height="800px" viewBox="0 0 1024 1024" class="icon"  version="1.1" xmlns="http://www.w3.org/2000/svg">
<path d="M419.847493 691.537171c-21.246751-16.838556-32.495766-40.218224-33.494791-61.035395-1.478556-30.8224 5.64199-66.562498 21.361639-107.222791a62.184273 62.184273 0 0 1 5.49963-0.824195c39.783649-4.183415 76.008273 30.237971 80.910985 76.879922 4.900215 46.641951-23.374673 87.841717-63.155824 92.022634a62.578888 62.578888 0 0 1-11.121639 0.179825z" fill="#FFFFFF" /><path d="M427.09042 771.746341h25.327765a24.97561 24.97561 0 0 0 23.297249-15.971902l35.61522-92.147512c0.504507-1.301229 0.896624-2.647415 1.176351-4.016078 2.75481-13.514302-5.969171-26.703922-19.485971-29.458732l-44.818732-9.138576-0.472039-0.089912c-13.566751-2.492566-26.586537 6.483668-29.079102 20.047922l-15.744624 85.666342-36.074771 6.87079A21.129366 21.129366 0 0 0 349.658537 754.263415a17.482927 17.482927 0 0 0 17.482926 17.482926h59.948957z" fill="#5DE4C7" /><path d="M396.462829 720.239141l14.81803-80.61877c3.241834-17.637776 20.165307-29.30638 37.803082-26.064547l0.6144 0.117386 44.82123 9.136078c17.570341 3.581502 28.911766 20.727259 25.332761 38.2976a33.010263 33.010263 0 0 1-1.528508 5.2224l-35.620214 92.15001A32.475785 32.475785 0 0 1 452.418185 779.239024H367.141463c-13.794029 0-24.97561-11.184078-24.975609-24.975609 0-13.74158 9.765463-25.545054 23.26478-28.115044l31.032195-5.90923zM452.418185 764.253659a17.477932 17.477932 0 0 0 16.306576-11.181581l35.617717-92.147512a17.482927 17.482927 0 0 0-12.814985-23.434615l-44.82123-9.131083c-9.827902-1.810732-18.939005 4.473132-20.687297 13.968859l-16.67122 90.711414-41.112351 7.829854A13.636683 13.636683 0 0 0 357.15122 754.263415a9.990244 9.990244 0 0 0 9.990243 9.990244h85.276722z" fill="#524F75" /><path d="M358.649756 761.526322l15.330029-3.873717a7.492683 7.492683 0 0 0-3.673912-14.53081l-15.330029 3.876215a7.492683 7.492683 0 1 0 3.673912 14.528312z" fill="#524F75" /><path d="M536.97561 771.746341h22.088429a24.97561 24.97561 0 0 0 24.878205-22.780253l5.254868-59.546849a25.00558 25.00558 0 0 0-1.463571-10.876878c-4.795317-12.932371-19.166283-19.528429-32.098653-14.73561l-32.33842 11.988293a24.973112 24.973112 0 0 0-16.29159 23.417132v29.004175l-27.782868 5.292332A21.129366 21.129366 0 0 0 462.04878 754.263415a17.482927 17.482927 0 0 0 17.482927 17.482926h57.443903z" fill="#5DE4C7" /><path d="M499.512195 722.017405v-22.805229c0-13.579239 8.449249-25.724878 21.179317-30.442771l32.335922-11.988293c16.81358-6.233912 35.497834 2.342712 41.729249 19.15879 1.675863 4.51559 2.325229 9.343376 1.903141 14.138693l-5.254868 59.546849A32.468293 32.468293 0 0 1 559.064039 779.239024H479.531707c-13.794029 0-24.97561-11.184078-24.975609-24.975609 0-13.74158 9.765463-25.545054 23.26478-28.115044l21.691317-4.130966zM559.064039 764.253659a17.482927 17.482927 0 0 0 17.415493-15.946927l5.25237-59.546849a17.482927 17.482927 0 0 0-23.492058-17.92999l-32.333424 11.988292a17.482927 17.482927 0 0 0-11.408859 16.393991v35.205619l-33.871922 6.4512A13.636683 13.636683 0 0 0 469.541463 754.263415a9.990244 9.990244 0 0 0 9.990244 9.990244h79.532332z" fill="#524F75" /><path d="M471.04 761.526322l15.330029-3.873717a7.492683 7.492683 0 0 0-3.673912-14.53081l-15.330029 3.876215a7.492683 7.492683 0 1 0 3.673912 14.528312z" fill="#524F75" /><path d="M273.123278 545.627161l2.777288 17.375532a24.978107 24.978107 0 0 0 20.754732 20.724761c7.325346 1.161366 12.8 1.630907 16.428956 1.411122 5.434693-0.329678 13.139668-3.241834 23.112429-8.736469a7.48519 7.48519 0 0 0 3.868722-6.888273l-0.207298-4.742868c19.106341 3.254322 36.152195 5.691941 51.137561 7.317854 17.378029 1.888156 45.238322 9.470751 83.583376 22.750282a7.492683 7.492683 0 0 0 9.945288-7.078087v-78.420917a7.492683 7.492683 0 0 0-8.356839-7.442732l-141.941386 16.488897-9.510712-3.18439-0.719297-12.417873a11.718556 11.718556 0 0 0-11.698576-11.03922 12.802498 12.802498 0 0 0-12.667629 10.939318l-1.8432 12.515278c-2.152898 0-4.240859 0.269737-6.23641 0.779239l-34.890927 1.735805a13.719102 13.719102 0 0 0-13.037268 13.699121 13.576741 13.576741 0 0 0 13.042263 13.566752l16.458927 0.646868z" fill="#5DE4C7" /><path d="M256.372137 552.46798a21.069424 21.069424 0 0 1-20.240235-21.054439 21.211785 21.211785 0 0 1 20.157815-21.184312l34.19161-1.700839c0.247259-0.054946 0.49202-0.109893 0.739278-0.159844l0.996527-6.77838a20.297678 20.297678 0 0 1 20.08039-17.340566 19.211239 19.211239 0 0 1 19.178771 18.097327l0.427083 7.355317 3.119453 1.04398 140.283005-16.294087a14.985366 14.985366 0 0 1 16.713678 14.885463v78.420917a14.985366 14.985366 0 0 1-19.890575 14.158673c-37.848039-13.109698-65.266263-20.57241-81.939981-22.383141-12.88242-1.396137-27.245893-3.384195-43.092917-5.966673a14.977873 14.977873 0 0 1-7.282888 9.395824c-10.86439 5.984156-19.473483 9.238478-26.276839 9.653073-4.288312 0.259746-10.237502-0.254751-18.054868-1.493541a32.468293 32.468293 0 0 1-26.981151-26.941191l-1.808234-11.311453-10.319922-0.402108z m76.003278 12.627669a7.492683 7.492683 0 0 1 8.741463-7.712469c18.96398 3.231844 35.862478 5.649483 50.688 7.255415 18.082341 1.963083 46.3872 9.668059 85.229268 23.12242v-78.420917l-141.941385 16.4864a7.432741 7.432741 0 0 1-3.241834-0.339669l-9.510712-3.179395a7.49518 7.49518 0 0 1-5.102517-6.673483l-0.721796-12.417873a4.225873 4.225873 0 0 0-4.21838-3.981112c-2.634927 0-4.870244 1.930615-5.254868 4.538068l-1.840703 12.520273a7.490185 7.490185 0 0 1-7.412761 6.398752c-1.498537 0-2.967102 0.18482-4.385717 0.546965-0.484527 0.124878-0.979044 0.199805-1.478556 0.224781l-34.893424 1.733307a6.223922 6.223922 0 0 0-5.916722 6.216429 6.081561 6.081561 0 0 0 5.844292 6.079064l16.458927 0.649366a7.490185 7.490185 0 0 1 7.105561 6.301346l2.777288 17.375532a17.487922 17.487922 0 0 0 14.528312 14.508331c6.830829 1.083941 11.835941 1.511024 14.803044 1.3312 4.071024-0.244761 10.869385-2.814751 19.94802-7.817365l-0.2048-4.745366z" fill="#524F75" /><path d="M273.29561 553.449522h19.985483a7.492683 7.492683 0 1 0 0-14.985366h-19.985483a7.492683 7.492683 0 0 0 0 14.985366z" fill="#524F75" /><path d="M582.815844 294.51239c5.452176 10.699551-7.530146 31.142088-38.939473 61.32761l-32.490771-63.772722c42.171317-9.068644 65.980566-8.254439 71.430244 2.445112z" fill="#FFC48B" /><path d="M576.541971 298.640859c-2.632429-5.64199-20.832156-7.370302-53.5552-2.332722l21.761249 46.664429c24.343727-22.915122 34.481327-38.564839 31.793951-44.331707z m13.579239-6.331318c7.200468 15.439922-7.692488 37.178693-42.843161 68.677932a7.492683 7.492683 0 0 1-11.790986-2.412644l-30.247961-64.866653a7.492683 7.492683 0 0 1 5.472157-10.542205c46.127454-8.249444 72.139551-6.448702 79.409951 9.14357z" fill="#524F75" /><path d="M600.181385 355.700137c4.775337 9.790439-7.322849 28.130029-36.292058 55.016273l-28.462205-58.365503c38.392507-7.55762 59.978927-6.44121 64.754263 3.34923z" fill="#FFC48B" /><path d="M562.653034 396.919883c11.381385-8.689015 19.810654-16.266615 25.247844-22.652878 5.577054-6.5536 7.330341-10.979278 6.643512-12.974829-0.661854-1.915629-4.600507-4.140956-12.839961-5.589542-8.154537-1.431102-19.398556-1.835707-33.649639-1.176351l14.598244 42.3936z m46.06002-40.507942c5.184937 15.055298-10.442302 33.407376-45.420644 58.695181a7.492683 7.492683 0 0 1-11.473795-3.633951l-21.141854-61.397542a7.492683 7.492683 0 0 1 6.541112-9.912819c42.750751-3.09198 66.257795 1.03399 71.495181 16.249131z" fill="#524F75" /><path d="M614.117776 421.291083c3.546537 10.302439-10.697054 27.028605-42.725776 50.183493l-21.141854-61.397542c39.029385-2.824741 60.321093 0.914107 63.86763 11.214049z" fill="#FFC48B" /><path d="M599.547005 438.426849c6.436215-5.711922 8.78642-9.85038 8.384312-11.923356-0.387122-1.988059-3.981112-4.740371-11.935844-7.320352-7.872312-2.552507-18.951493-4.518088-33.157619-5.849287l8.556644 44.014517c12.475317-7.020644 21.878634-13.351961 28.152507-18.921522z m23.092449-14.783064c3.039532 15.629737-14.990361 31.63161-53.1456 51.80441a7.49518 7.49518 0 0 1-10.859395-5.194927l-12.3904-63.742751a7.492683 7.492683 0 0 1 7.857326-8.903805c42.763239 2.884683 65.468566 10.242498 68.538069 26.037073z" fill="#524F75" /><path d="M622.177405 470.490537c5.53959 8.863844-3.067005 26.888741-25.812293 54.069697l-33.015258-52.830907c33.67961-9.690537 53.287961-10.102634 58.827551-1.23879z" fill="#FFC48B" /><path d="M613.203668 487.011902c3.069502-7.048117 3.404176-11.343922 2.250303-13.054751-1.103922-1.6384-5.00761-2.799766-12.437854-2.385171-7.165502 0.402107-16.606283 2.285268-28.242419 5.664469l23.324722 34.578731c7.160507-9.827902 12.198088-18.122302 15.105248-24.803278z m14.673171-21.43157c8.556644 12.680117-0.31719 33.067707-24.208859 63.735258a7.49518 7.49518 0 0 1-12.12316-0.414595l-34.838479-51.649561a7.492683 7.492683 0 0 1 3.893698-11.313951c36.664195-11.950829 58.630244-13.179629 67.2768-0.357151z" fill="#524F75" /><path d="M651.308956 502.14962c8.206985 4.930185 8.679024 23.219824 1.416117 54.866419l-48.912234-29.391298c23.45959-21.916098 39.289132-30.407805 47.496117-25.475121z" fill="#FFC48B" /><path d="M650.419824 520.112078c0.057444-6.848312-1.1264-10.394849-2.48757-11.281483-1.291239-0.836683-4.782829-0.444566-10.72203 2.480078-5.696937 2.804761-12.720078 7.562615-20.992 14.261073l30.560156 19.84562c2.372683-10.404839 3.581502-18.864078 3.641444-25.305288z m5.671961-23.846712c12.09319 7.852332 11.908371 28.409756 2.6624 63.093385a7.492683 7.492683 0 0 1-11.321444 4.353249l-47.858263-31.077151a7.490185 7.490185 0 0 1-0.83918-11.933347c26.861268-23.394654 45.123434-32.380878 57.356487-24.436136z" fill="#524F75" /><path d="M699.946459 502.511766c8.861346 1.088937 16.19918 16.488898 22.018497 46.204878l-52.820917-6.486166c11.6736-27.568078 21.938576-40.807649 30.80242-39.718712z" fill="#FFC48B" /><path d="M705.121405 517.85678c-2.87719-5.5296-5.284839-7.814868-6.583571-7.929756-0.369639-0.032468-0.966556 0.152351-1.950595 0.826693-1.540995 1.056468-3.356722 2.952117-5.339785 5.699434-3.356722 4.657951-6.945717 11.403863-10.714537 20.197776l32.44082 2.839727c-2.535024-9.240976-5.167454-16.468917-7.852332-21.633874z m-5.277346-22.860175c13.7216 1.201327 22.637893 18.344585 30.267941 51.177522a7.49518 7.49518 0 0 1-7.954732 9.161053l-53.018224-4.63797a7.492683 7.492683 0 0 1-6.343805-10.142595c11.963317-31.244488 23.159883-46.771824 37.04882-45.55801z" fill="#524F75" /><path d="M356.821541 272.883512c29.793405-12.213073 63.970029-15.185171 103.206713 0s84.415063 80.036839 99.879961 138.272468c4.735376 17.832585 7.035629 34.588722 6.900761 50.270908-0.41959 48.003122 35.894946 88.373698 83.673287 93.016663 17.313093 1.683356 62.736234-13.863961 94.442771-42.103883 11.174088-12.907395 18.187239-18.666771 21.046946-17.275629 4.285815 2.085463 1.301229 15.737132 0.796722 17.275629-16.59879 50.805385-31.686556 68.740371-50.842848 85.743766s-41.112351 32.418341-65.443591 42.770732c-9.765463 27.533112-49.099551 52.406322-80.341541 62.344117s-57.771083 14.01881-103.386537 8.354341-78.588254-43.162849-80.40398-81.048351c-1.933112-40.308137 10.379863-88.238829 36.941424-143.794575a7.487688 7.487688 0 0 0-6.089053-10.694557c-52.993249-4.765346-85.341659-11.481288-97.042732-20.150321C293.798088 436.328898 284.721951 408.813268 284.721951 374.436839c0-49.299356 42.306185-89.342751 72.09959-101.553327z" fill="#5DE4C7" /><path d="M356.821541 272.883512C327.028137 285.094088 284.721951 325.137483 284.721951 374.436839c0 34.376429 9.076137 61.892059 35.437893 81.425483 11.701073 8.669034 44.049483 15.387473 97.042732 20.150322a7.492683 7.492683 0 0 1 6.089053 10.694556c-26.561561 55.555746-38.874537 103.488937-36.941424 143.794576 1.818224 37.885502 34.791024 75.383883 80.40398 81.048351s72.144546 1.583454 103.386537-8.354342 70.576078-34.811005 80.341541-62.344117c24.331239-10.35239 46.2848-25.767337 65.443591-42.770731s34.246556-34.93838 50.842848-85.743766c0.50201-1.538498 3.486595-15.190166-0.796722-17.27563-2.859707-1.391141-9.872859 4.368234-21.046946 17.27563-31.706537 28.24242-77.132176 43.787239-94.442771 42.103883-47.778341-4.642966-84.092878-45.013541-83.673287-93.016664 0.137366-15.682185-2.165385-32.438322-6.900761-50.270907-15.464898-58.233132-60.643278-123.0848-99.879961-138.269971s-73.413307-12.213073-103.206713 0z m392.239454 213.873639c2.709854-2.225327 5.259863-3.921171 7.924761-5.100019 4.877737-2.157893 10.145093-2.694868 15.54482-0.067434 6.084059 2.95961 8.993717 8.074615 10.14759 13.93639 0.589424 2.987083 0.674341 6.086556 0.439571 9.438283-0.3072 4.315785-1.258771 9.450771-2.102947 12.028253-15.454907 47.313795-29.710985 69.731902-55.141151 92.299864-20.395083 18.097327-41.674302 32.615649-63.91758 42.865639-13.566751 27.902751-50.171005 53.520234-87.272274 65.318712-36.759102 11.69358-65.503532 14.443395-109.775297 8.943766-51.112585-6.3488-91.278361-48.34279-93.526166-95.202029-1.950595-40.665288 9.435785-87.706849 33.864429-141.287025-49.686478-4.957659-80.146732-11.761015-94.008195-22.030985-29.021659-21.501502-41.501971-52.044176-41.501971-93.463727 0-26.544078 10.394849-52.059161 28.207454-74.102634 15.07278-18.654283 34.870946-33.806985 53.193054-41.317151 36.159688-14.823024 74.162576-15.644722 114.300878-0.109893 43.60242 16.87602 92.035122 84.697288 108.956097 148.402576 5.067551 19.081366 7.547629 37.163707 7.400273 54.249522-0.352156 40.235707 30.090615 74.075161 70.139005 77.971356 15.659707 1.521015 56.764566-15.35001 82.332098-37.763122 5.796839-6.656 10.662088-11.618654 14.795551-15.010342z" fill="#524F75" /><path d="M312.195122 392.117073a7.492683 7.492683 0 0 1 7.492683 7.492683v14.985366a7.492683 7.492683 0 1 1-14.985366 0v-14.985366a7.492683 7.492683 0 0 1 7.492683-7.492683zM347.160976 392.117073a7.492683 7.492683 0 0 1 7.492683 7.492683v14.985366a7.492683 7.492683 0 1 1-14.985366 0v-14.985366a7.492683 7.492683 0 0 1 7.492683-7.492683z" fill="#44756A" /><path d="M405.069424 489.951532c10.911844 1.138888 19.840624 1.138888 26.891239-0.064937 21.561444-3.688898 28.309854-6.211434 41.364605-17.313093a7.492683 7.492683 0 1 0-9.708019-11.416351c-10.619629 9.03118-15.035317 10.679571-34.186615 13.956371-5.50962 0.94158-13.144663 0.94158-22.807727-0.067434a7.492683 7.492683 0 1 0-1.553483 14.905444z" fill="#524F75" /><path d="M419.847493 691.537171c-21.246751-16.838556-32.498263-40.218224-33.497288-61.035395-1.476059-30.8224 5.64199-66.562498 21.361639-107.220293a62.184273 62.184273 0 0 1 5.499629-0.824195c39.783649-4.183415 76.008273 30.237971 80.910986 76.879922 4.900215 46.641951-23.374673 87.841717-63.155825 92.022634-3.746341 0.392117-7.460215 0.444566-11.119141 0.177327z" fill="#FFFFFF" /><path d="M404.689795 261.144976L364.024507 257.973073C383.77522 213.926088 415.264468 195.391688 458.484761 202.369873 501.707551 209.345561 521.920312 239.293815 519.120546 292.214634H463.514849c-0.574439-33.819473-8.117073-52.533698-22.632898-56.147668-14.515824-3.611473-26.579044 4.745366-36.192156 25.07801z" fill="#FFF185" /><path d="M442.690185 228.796566c17.645268 4.390712 26.444176 23.519532 28.072586 55.925385H511.875122C512.449561 239.935688 494.517073 215.774283 457.290927 209.765151 420.821541 203.880898 394.020215 217.3952 375.625678 251.362029l24.640937 1.923122c10.759493-19.953015 25.145444-28.789385 42.42357-24.488585zM352.832937 264.614088l4.353248-9.70802C378.283083 207.867005 412.98919 187.436956 459.678595 194.972098 506.979902 202.607141 529.590322 236.111922 526.600741 292.611746L526.22361 299.707317H456.147044l-0.124878-7.365307c-0.52199-30.759961-6.863298-46.492098-16.950946-49.004644-10.459785-2.602459-19.358595 3.561522-27.605542 21.009483l-2.207844 4.670439L352.832937 264.614088z" fill="#524F75" /><path d="M499.512195 304.702439m-47.453658 0a47.453659 47.453659 0 1 0 94.907317 0 47.453659 47.453659 0 1 0-94.907317 0Z" fill="#FFF185" /><path d="M499.512195 359.64878c-30.345366 0-54.946341-24.600976-54.946341-54.946341s24.600976-54.946341 54.946341-54.946341 54.946341 24.600976 54.946342 54.946341-24.600976 54.946341-54.946342 54.946341z m0-14.985365c22.068449 0 39.960976-17.892527 39.960976-39.960976s-17.892527-39.960976-39.960976-39.960976-39.960976 17.892527-39.960975 39.960976 17.892527 39.960976 39.960975 39.960976z" fill="#524F75" /><path d="M507.004878 297.209756m-24.97561 0a24.97561 24.97561 0 1 0 49.95122 0 24.97561 24.97561 0 1 0-49.95122 0Z" fill="#FFFBDC" /><path d="M312.195122 302.204878m-37.463415 0a37.463415 37.463415 0 1 0 74.92683 0 37.463415 37.463415 0 1 0-74.92683 0Z" fill="#FFFFFF" /><path d="M312.195122 347.160976C287.366868 347.160976 267.239024 327.033132 267.239024 302.204878S287.366868 257.24878 312.195122 257.24878s44.956098 20.127844 44.956098 44.956098-20.127844 44.956098-44.956098 44.956098z m0-14.985366c16.551337 0 29.970732-13.419395 29.970732-29.970732S328.746459 272.234146 312.195122 272.234146 282.22439 285.653541 282.22439 302.204878s13.419395 29.970732 29.970732 29.970732z" fill="#524F75" /><path d="M292.446907 310.798985A11.239024 11.239024 0 1 0 289.717073 303.22638l8.331864 1.211318-5.60203 6.361287z" fill="#232323" /><path d="M498.458224 472.543532c7.662517-16.416468 12.495298-30.342868 14.498342-41.781698 1.153873-19.381073 1.153873-32.445815 0-39.194224-0.3072-1.790751-2.497561-4.810302-6.571083-9.058654-13.621698-3.711376-22.528-17.178224-20.235239-31.431805C488.987473 333.431883 504.762068 320.826693 522.599649 321.950595l21.511492 1.356176c15.464898 0.976546 27.732917 12.879922 29.558635 27.850302 4.770341 2.769795 9.588137 7.442732 9.448273 13.389425-0.304702 13.002302-8.569132 18.269659-18.11481 19.615843l-13.444371 1.893152 7.357815 35.273053c1.940605 11.853424 6.086556 23.487063 6.086556 38.122771l-6.086556 45.655415" fill="#5DE4C7" /><path d="M552.273171 426.650849c0.279727 1.41362 0.589424 2.882185 0.976546 4.62798 0.147356 0.674341 0.299707 1.358673 0.507005 2.280273l0.507005 2.265288c2.282771 10.23001 3.204371 16.131746 3.246829 23.139903l-6.016624 45.153405a7.492683 7.492683 0 1 0 14.852995 1.978068l6.084058-45.655415c0.044956-0.32718 0.067434-0.659356 0.067435-0.989034 0-8.59161-1.048976-15.429932-3.608976-26.891239l-0.509503-2.277776-0.494517-2.225326a184.817015 184.817015 0 0 1-0.909112-4.318283 124.42599 124.42599 0 0 1-0.661853-3.621464l-5.779357-27.757892 5.517113-0.776742c14.513327-2.043005 24.196371-11.179083 24.561014-26.858771 0.172332-7.387785-3.88121-13.546771-10.107629-18.054868A39.30162 39.30162 0 0 0 544.585678 315.831571l-21.511493-1.356176C501.382868 313.104234 482.2016 328.431766 478.752468 349.888312c-2.762302 17.195707 7.357815 33.67961 23.527025 39.196722 1.176351 1.286244 2.092956 2.385171 2.739824 3.2768 0.284722 0.392117 0.494517 0.714302 0.629385 0.949073 0.94158 6.13401 0.9216 18.474459-0.144858 36.574283-1.920624 10.634615-6.521132 23.829229-13.83399 39.491434a7.492683 7.492683 0 0 0 13.576741 6.341308c7.919766-16.963434 12.959844-31.486751 15.090264-43.657366 0.049951-0.279727 0.08242-0.561951 0.099902-0.846673 1.188839-19.940527 1.188839-33.409873-0.094907-40.902556-0.654361-3.826263-3.404176-7.620059-8.546654-12.982322a7.500176 7.500176 0 0 0-3.436644-2.043005c-10.037698-2.734829-16.473912-12.652644-14.808039-23.015025a27.208429 27.208429 0 0 1 28.577093-22.837697l21.511492 1.356175a24.311259 24.311259 0 0 1 22.595435 21.27922 7.48519 7.48519 0 0 0 3.673912 5.572058c3.69639 2.145405 5.766868 4.767844 5.721912 6.733425-0.179824 7.739941-3.941151 11.28398-11.671102 12.372917l-13.441874 1.893151a7.492683 7.492683 0 0 0-6.291356 8.948761l7.325347 35.118205c0.209795 1.261268 0.449561 2.562498 0.721795 3.943649z" fill="#524F75" /><path d="M555.707317 528.234146m-8.741463 0a8.741463 8.741463 0 1 0 17.482926 0 8.741463 8.741463 0 1 0-17.482926 0Z" fill="#524F75" /><path d="M514.05799 326.683473l-2.340214 15.764605a7.492683 7.492683 0 1 0 14.820526 2.200351l2.342713-15.764605a7.492683 7.492683 0 0 0-14.823025-2.200351zM539.0336 329.181034l-2.340215 15.764605a7.492683 7.492683 0 1 0 14.820527 2.200351l2.342712-15.764605a7.492683 7.492683 0 0 0-14.823024-2.200351z" fill="#524F75" /><path d="M389.619512 289.717073m-47.453658 0a47.453659 47.453659 0 1 0 94.907317 0 47.453659 47.453659 0 1 0-94.907317 0Z" fill="#FFFFFF" /><path d="M389.619512 344.663415C359.274146 344.663415 334.673171 320.062439 334.673171 289.717073S359.274146 234.770732 389.619512 234.770732s54.946341 24.600976 54.946342 54.946341-24.600976 54.946341-54.946342 54.946342z m0-14.985366c22.068449 0 39.960976-17.892527 39.960976-39.960976S411.687961 249.756098 389.619512 249.756098 349.658537 267.648624 349.658537 289.717073s17.892527 39.960976 39.960975 39.960976z" fill="#524F75" /><path d="M365.787785 302.007571A14.985366 14.985366 0 1 0 362.146341 291.909932l11.109152 1.615922-7.467708 8.481717z" fill="#232323" />
</svg>

          </div>
          <div class="dialog-text">
          <p>Ignore `hx-redirect` header for now, this was a snippet of code that I had laying around on github. Also, note that the responses I return in case of errors are not very exhaustive for most scenarios, I'm conciously leaving out the details because it's not the focus of this blog post.</p>
          </div>
        </div>
<div class="paragraph">
<p>If <code>login</code> is successful the user will be redirected to the homepage at <code>/</code> and
will trigger the <code>home</code> endpoint again but his navbar will still show the login
button because we&#8217;re using <code>Context::default()</code>. Let&#8217;s change that with our
first approach using Axum extractors.</p>
</div>
<div class="paragraph">
<p>When I first started using Axum I really liked the idea of <code>Extractors</code>, if
you&#8217;ve used the framework you&#8217;re probably familiar with them (i.e <code>Json</code>,
<code>Form</code> etc.). Everything that implements <code>FromRequest</code> or
<code>FromRequestParts</code> (and the <code>Option</code> alternative since Axum 0.8!) can be
considered an extractor and can be used in the function signature to get
something out of a request.</p>
</div>
<div class="paragraph">
<p>In our case, we would like to get some user data out of a request (cookies are
always sent with an HTTP request), in particular we can create a custom
extractor that tries to extract our user data from the jwt token in the user&#8217;s
request, if present. Let&#8217;s implement <code>CookieJwt&lt;T&gt;</code> which we&#8217;re going to use to
get that information out of requests that reaches our endpoints.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-rust" data-lang="rust">/// Basic claims that a classic jwt contain
#[derive(Debug, Serialize, Deserialize)]
pub struct Claims {
    pub sub: String,
    pub exp: usize,
    pub user_id: uuid::Uuid,
}

/// A flexible extractor that tries
/// to get a type `T` from a request cookie
#[derive(Debug, PartialEq, Eq, Clone)]
pub struct CookieJwt&lt;T: DeserializeOwned&gt;(pub T);

// since axum 0.8 you can implement extractors meant to be Option&lt;T&gt;
// this is very useful, expecially for scenarios where endpoint can be accessed
// both by authed users and non-authed users
impl&lt;S, T&gt; OptionalFromRequestParts&lt;S&gt; for CookieJwt&lt;T&gt;
where
    AppState: FromRef&lt;S&gt;,
    S: Send + Sync,
    T: DeserializeOwned,
{
    type Rejection = Redirect;

    async fn from_request_parts(
        req: &amp;mut Parts,
        state: &amp;S,
    ) -&gt; Result&lt;Option&lt;Self&gt;, Self::Rejection&gt; {
        let jar = CookieJar::from_headers(&amp;req.headers);
        if let Some(jwt) = jar.get("jwt").map(|c| c.value()) {
            return match validate_jwt::&lt;T&gt;(JWT_SIGNING_KEY, jwt) {
                Ok(data) =&gt; return Ok(Some(CookieJwt(data))),
                // user tampered with cookie here, we want to delete that cookie
                // returning None here would have been okay too if you're okay with
                // manufactured cookies :)
                Err(_) =&gt; Err(Redirect::to("/logout")),
            };
        }

        // if refresh token is present, try and get a new jwt
        // by redirecting user to /refresh_token endpoint
        if jar.get("refresh").is_some() {
            return Err(Redirect::to(
                format!("/refresh_token?next={}", req.uri).as_str(),
            ));
        }

        // at this point, user has no jwt and no refresh token
        Ok(None)
    }
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>And we can use our brand new extractor in our <code>home</code> function</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-rust" data-lang="rust">pub async fn home(jwt: Option&lt;CookieJwt&lt;Claims&gt;&gt;) -&gt; impl IntoResponse {
    HtmlTemplate(
        HomeTemplate { ctx: Context { authed: jwt.is_some() } }
    ).into_response()
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>Now each time try and navigate to <code>/</code> the extractor is going to peek into your
request and look for <code>jwt</code> and <code>refresh</code> cookies, if <code>jwt</code> is found and can be
decoded to <code>Claims</code> then <code>jwt: Option&lt;_&gt;</code> is going to contain <code>Some(jwt)</code> data
and our user will see the "Profile" button in his navbar, indicating he&#8217;s
correctly logged in. If neither of the cookies is found then the user will be
returned the classic navbar with the option to "Login". If however <code>jwt</code> can&#8217;t
be found but a <code>refresh</code> cookie is present we can still do something for the user
and get him a proper <code>jwt</code>.</p>
</div>
<div class="paragraph">
<p>Indeed, the logic implemented above will redirect the user to <code>/refresh_token</code>
along with a query parameter indicating where the user was previously
navigating to. This way we&#8217;re not distrupting the original user&#8217;s intent and
everything is going to happen in a quick succession of requests. How does our
<code>/refresh_token</code> endpoint look like?</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-rust" data-lang="rust">#[derive(Debug, Deserialize)]
pub struct RefreshTokenQuery {
    next: Option&lt;String&gt;,
}

pub async fn refresh_token(
    State(app): State&lt;AppState&gt;,
    jar: CookieJar,
    Query(RefreshTokenQuery { next }): Query&lt;RefreshTokenQuery&gt;,
) -&gt; impl IntoResponse {
    let token = match jar.get("refresh") {
        Some(token) =&gt; token,
        None =&gt; {
            // if there's no token then the user goes back to /login
            return Redirect::to("/login").into_response();
        }
    };

    // if something goes wrong here we remove the token, otherwise the user could end up
    // in a loop where he's constantly being redirected here and this function fails every time
    let user = match db::refresh_tokens::get_user(&amp;app.pg_pool, token.value()).await {
        Ok(Some(user)) =&gt; user,
        _ =&gt; {
            return (jar.remove(Cookie::from("refresh")), Redirect::to("/login")).into_response();
        }
    };

    // set new jwt
    let claims = Claims::with(user.email, user.id);
    match jwt::generate_jwt(app.jwt_signing_key.as_bytes(), claims) {
        Ok(token) =&gt; (
            jar.add(default_cookie("jwt", token, 1)),
            Redirect::to(&amp;next.unwrap_or("/".to_owned())),
        )
        .into_response(),
        Err(_) =&gt; {
            (jar.remove(Cookie::from("refresh")), Redirect::to("/login")).into_response()
        }
    }
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>Nothing surprising here, our refresh token endpoint is going to check that the
<code>refresh</code> cookie is part of the request and if it is it will try to ask the db to
return the user information associated to that refresh token. Once the
information is retrieved it re-generates the valid <code>jwt</code> and redirect the user
to his previous url <code>next</code>, if present.</p>
</div>
<div class="paragraph">
<p>Even though it is a great starting point and has worked very well for me, it&#8217;s
not flawless:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>It doesn&#8217;t feel right: handling authentication logic in an extractor doesn&#8217;t
feel quite right.</p>
</li>
<li>
<p>It&#8217;s not flexible for more complex authentication scenarios i.e restricting
some endpoints to users with a specific role.</p>
</li>
<li>
<p>If a user sends a POST request that has a body attached to it the
<code>/refresh_token</code> redirect will break that flow because almost every browser
won&#8217;t expect a <code>302</code> redirect to have a body.</p>
</li>
</ul>
</div>
<div class="paragraph">
<p>If you’re a backend developer, authentication screams middleware. To level up
the cookie-based authentication we’ve discussed, authentication middleware
offers a cleaner, reusable way to validate cookies and secure routes.</p>
</div>
<div class="paragraph">
<p>Axum gives you quite a few options when you want to implement a
<a href="https://docs.rs/axum/latest/axum/middleware/index.html">middleware</a>. You don&#8217;t have to give up on the granularity
that extractor provided because axum middleware can be applied at the app level
down to the individual route level.</p>
</div>
<div class="quoteblock">
<blockquote>
<div class="paragraph">
<p>Axum allows you to add middleware just about anywhere</p>
</div>
</blockquote>
</div>
<div class="paragraph">
<p>The easiest way to implement an Axum middleware is to create a function that
matches the <a href="https://docs.rs/axum/latest/axum/middleware/fn.from_fn.html"><code>axum::middleware::from_fn</code></a> (or
<a href="https://docs.rs/axum/latest/axum/middleware/fn.from_fn_with_state.html"><code>axum::middleware::from_fn_with_sate</code></a> if you need
<code>State</code>) function. The requirements are pretty straightfoward:</p>
</div>
<div class="quoteblock">
<blockquote>
<div class="olist arabic">
<ol class="arabic">
<li>
<p>Be an async <code>fn</code>.</p>
</li>
<li>
<p>Take zero or more <code>FromRequestParts</code> extractors.</p>
</li>
<li>
<p>Take exactly one <code>FromRequest</code> extractor as the second to last argument.</p>
</li>
<li>
<p>Take <code>Next</code> as the last argument.</p>
</li>
<li>
<p>Return something that implements <code>IntoResponse</code>.</p>
</li>
</ol>
</div>
</blockquote>
</div>
<div class="paragraph">
<p>With that in mind, let&#8217;s try and create our authentication middleware.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-rust" data-lang="rust">/// Middleware that handles both authenticated and unauthenticated requests.
///
/// This middleware performs JWT-based authentication by checking for `jwt` and `refresh` cookies.
/// It establishes a [`UserContext`] that flows through the request chain and manages cookie updates.
///
/// # Behavior
/// - **JWT Present**: Validates the JWT and extracts user claims if successful.
///   - Invalid JWT: Clears auth cookies (potential tampering)
/// - **No JWT but Refresh Token Present**:
///   - Attempts to refresh the token and issue a new JWT
///   - On success: Sets new cookies and establishes authenticated context
/// - **No Auth Cookies**: Proceeds with default unauthenticated context
///
/// # Cookie Management
/// - Automatically removes suspicious/invalid auth cookies
/// - Adds new JWT cookies when refresh is successful
/// - Propagates all cookie changes in the response
pub async fn base(
    State(app): State&lt;AppState&gt;,
    mut request: Request,
    next: Next,
) -&gt; impl IntoResponse {
    let mut jar = CookieJar::from_headers(request.headers());
    let jwt = jar.get("jwt");
    let refresh = jar.get("refresh");

    // Default context for unauthenticated requests
    let mut context = UserContext {
        user_id: None,
        is_admin: false,
    };

    // JWT takes precedence if present
    if let Some(jwt) = jwt {
        match validate_jwt::&lt;Claims&gt;(JWT_SIGNING_KEY, jwt.value()) {
            Ok(claims) =&gt; {
                context.user_id = Some(claims.user_id);
            }
            Err(_) =&gt; {
                // Clear potentially compromised cookies
                jar = jar.remove("jwt").remove("refresh");
            }
        }
    }
    // Fall back to refresh token if JWT is absent/invalid
    else if let Some(refresh) = refresh {
        if let Ok(Some(user)) = db::refresh_tokens::get_user(&amp;app.pg_pool, refresh.value()).await {
            let claims = Claims::with(user.email, user.uuid);
            if let Ok(jwt) = generate_jwt(app.jwt_signing_key.as_bytes(), claims) {
                context.user_id = Some(user.uuid);
                jar = jar.add(default_cookie("jwt", jwt, 1));
            }
            // Note: JWT generation errors are intentionally swallowed here
            // to prevent refresh token from being invalidated due to
            // temporary JWT generation issues
        }
    }

    // Inject the resolved context into request extensions
    request.extensions_mut().insert(context);

    let response = next.run(request).await;

    // Merge cookie updates with the response
    (jar, response).into_response()
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>The middleware we&#8217;ve built takes the same core idea as our initial extractor
but makes it far more powerful. Unlike a simple extractor, middleware can
intercept and modify responses and modify it as needed. This enables us to do
much more interesting things.</p>
</div>
<div class="paragraph">
<p>First of all, the middleware initializes the <code>UserContext</code> with some default
values that an un-authenticated users will reflect. After that, it goes through
the first authentication step which tries to look for a valid <code>jwt</code> token in
the request&#8217;s cookies, if it finds one it updates the <code>UserContext</code> accordingly
with the data decoded from the <code>jwt</code>. If a <code>jwt</code> token is not found, it falls
back to the <code>refresh</code> token and uses it to generate a valid <code>jwt</code> for the user
and updates the <code>UserContext</code> accordingly. The authentication part of
middleware is now complete and the <code>UserContext</code> is passed along with the
request so that handlers can make use of it. But we&#8217;re not done yet! The
middleware will wait for the <code>response</code> returned by whatever we have running in
<code>next.run(_)</code> and does something pretty cool: in case the request wasn&#8217;t
originally authenticated (did not have a <code>jwt</code> attached) it sends back with the
response new a new cookie containing the generated <code>jwt</code>.</p>
</div>
<div class="paragraph">
<p>This last part is very cool for different reasons:</p>
</div>
<div class="olist arabic">
<ol class="arabic">
<li>
<p><strong>Silent Authentication</strong>: Requests that come in un-authenticated will be
treated as authenticated (if <code>refresh</code> is present!) because we do the heavy
lifting of generating the <code>jwt</code> in the middleware.</p>
</li>
<li>
<p><strong>Works with all request types</strong>: whatever the request was (POST, PUT, GET
etc.), the middleware won&#8217;t distrupt the flow and the user will get back a
fresh <code>jwt</code> if he&#8217;s missing one.</p>
</li>
<li>
<p><strong>Simplified Architecture</strong>: with this middleware we don&#8217;t need extra round trips
to authenticate the user, therefore we can also get rid of the
<code>/refresh_token</code> endpoint.</p>
</li>
</ol>
</div>
<div class="paragraph">
<p>Our new <code>home</code> endpoint now would end up looking like this</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-rust" data-lang="rust">pub async fn home(Extension(usr_ctx): Extension&lt;UserContext&gt;) -&gt; impl IntoResponse {
    HtmlTemplate(
        HomeTemplate { ctx: Context { authed: usr_ctx.user_id.is_some() } }
    ).into_response()
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>Nothing is stopping us from generating a <code>Context</code> directly in the middleware,
that would actually be a better approach here so that we can pop it in
directly in the template</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-rust" data-lang="rust">pub async fn home(Extension(ctx): Extension&lt;Context&gt;) -&gt; impl IntoResponse {
    HtmlTemplate(HomeTemplate { ctx }).into_response()
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>We&#8217;re not done yet - one last cool thing that you can do with
middlewares is stack them on top of each other and have multiple layers of
logic to protect different parts of your backend, just like an onion.</p>
</div>
<div class="paragraph">
<p>Let&#8217;s consider the scenario where you want some parts of your application to be
public, some others to be for authenticated only users and then you have a very
special dashboard that only super admins can access. You can leverage middlewares
to implement all of those protection layers</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-rust" data-lang="rust">/// middleware that requires the user to be authenticated
pub async fn required_auth(
    Extension(context): Extension&lt;UserContext&gt;,
    request: Request,
    next: Next
) -&gt; impl IntoResponse {
    if context.user_id.is_none() {
        return Redirect::to("/login").into_response();
    }

    next.run(request).await
}

/// middleware that requires the user to be authenticated
pub async fn required_admin(
    Extension(context): Extension&lt;UserContext&gt;,
    request: Request,
    next: Next,
) -&gt; impl IntoResponse {
    if !context.is_admin {
        return Redirect::to("/").into_response();
    }

    next.run(request).await
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>If you remember correctly, middlewares can have zero or more <code>FromRequestParts</code>
in its signature, which means you can use as many extractors as you want to and
<code>Extension</code> is an extractor too! This means you can re-use something that the
previous middleware computed in the following middlewares. The only thing you
have to pay attention to in this case is to apply the middlewares in the
correct order. This is a pretty good look of how middlewares work in Axum</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-Graph" data-lang="Graph">+-----------------------+
|       Requests        |
+-----------------------+
           |
           v
+-----------------------+
|      Layer Three      |
|  +-----------------+  |
|  |    Layer Two    |  |
|  |  +-----------+  |  |
|  |  | Layer One |  |  |
|  |  |   +---+   |  |  |
|  |  |   | H |   |  |  |
|  |  |   | a |   |  |  |
|  |  |   | n |   |  |  |
|  |  |   | d |   |  |  |
|  |  |   | l |   |  |  |
|  |  |   | e |   |  |  |
|  |  |   | r |   |  |  |
|  |  |   +---+   |  |  |
|  |  +-----------+  |  |
|  +-----------------+  |
+-----------------------+
           |
           v
+-----------------------+
|      Responses        |
+-----------------------+</code></pre>
</div>
</div>
<div class="paragraph">
<p>It really is like an onion after all</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-rust" data-lang="rust">let app = Router::new()
    .route("/admin", get(admin::get))
    // only admins can access the routes above
    .layer(
        middleware::from_fn_with_state(state.clone(), required_admin)
    )
    .route("/profile", get(profile::get))
    // routes above will need to be authenticated
    .layer(
        middleware::from_fn_with_state(state.clone(), required_auth)
    )
    .route("/", get(home))
    // most external layer, will provide
    // `Extension&lt;UserContext&gt;` to all the routes above
    .layer(
        middleware::from_fn_with_state(state.clone(), base)
    );</code></pre>
</div>
</div>
<div class="paragraph">
<p>For better readability you can also create different routers with different
layers and finally merge them together into the main app&#8217;s router.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-rust" data-lang="rust">let admin = Router::new()
    .route("/admin", get(handler))
    .layer(
        middleware::from_fn_with_state(state.clone(), required_admin)
    );

let protected = Router::new()
    .route("/profile")
    .layer(
        middleware::from_fn_with_state(state.clone(), required_auth)
    );

let public = Router::new()
    .route("/");

let app = Router::new()
    .merge(public)
    .merge(protected)
    .merge(admin);
    .layer(
        middleware::from_fn_with_state(state.clone(), base)
    )</code></pre>
</div>
</div>
<div class="paragraph">
<p>I&#8217;ve been playing with middlewares for a while now in Axum and I feel they
provide a much better option for this scenario than creative alternatives like
the one I&#8217;ve talked about initially. Axum provides much more powerful features
for middlewares if you need it, but I still haven&#8217;t delved into those that much
because there was no need for me to do it, I almost always can get stuff done
with the simple <code>middleware::from_fn_with_sate</code> function. You should give them
a try!</p>
</div>]]></content><author><name>ohmycloud</name></author><summary type="html"><![CDATA[Consider this scenario: you&#8217;re building a website that has a classic navbar at the top, this navbar has a button that reflects the user authentication status, showing a "Profile" button if the user is authenticated and showing a "Login" button in case the user is unauthenticated.]]></summary></entry><entry><title type="html">Rust Books That I Read</title><link href="https://ohmycloud.github.io/2024/10/01/rust-books-that-i-read.html" rel="alternate" type="text/html" title="Rust Books That I Read" /><published>2024-10-01T00:00:00+00:00</published><updated>2024-10-01T00:00:00+00:00</updated><id>https://ohmycloud.github.io/2024/10/01/rust-books-that-i-read</id><content type="html" xml:base="https://ohmycloud.github.io/2024/10/01/rust-books-that-i-read.html"><![CDATA[<table class="tableblock frame-all grid-all stretch">
<colgroup>
<col style="width: 50%;">
<col style="width: 50%;">
</colgroup>
<tbody>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">Title</p></td>
<td class="tableblock halign-center valign-top"><p class="tableblock">Desc</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">精通 Rust（第2版）</p></td>
<td class="tableblock halign-center valign-top"><p class="tableblock">Done</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">Black Hat Rust</p></td>
<td class="tableblock halign-center valign-top"><p class="tableblock">34%</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">Code Like a Pro in Rust</p></td>
<td class="tableblock halign-center valign-top"><p class="tableblock">Done</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">Learn Rust in a Month of Lunches</p></td>
<td class="tableblock halign-center valign-top"><p class="tableblock">Done</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">Rust in Action</p></td>
<td class="tableblock halign-center valign-top"><p class="tableblock">1%</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">Rust Servers Services and Apps</p></td>
<td class="tableblock halign-center valign-top"><p class="tableblock">4%</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">Rust Web Development</p></td>
<td class="tableblock halign-center valign-top"><p class="tableblock">41%</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">Mastering Rust Programming</p></td>
<td class="tableblock halign-center valign-top"><p class="tableblock">26%</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">Command-Line Rust</p></td>
<td class="tableblock halign-center valign-top"><p class="tableblock">Done</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">Programming Rust</p></td>
<td class="tableblock halign-center valign-top"><p class="tableblock">Done</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">Rust Atomics</p></td>
<td class="tableblock halign-center valign-top"><p class="tableblock">15%</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">Programming with Rust</p></td>
<td class="tableblock halign-center valign-top"><p class="tableblock">15%</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">Rust for the IoT</p></td>
<td class="tableblock halign-center valign-top"><p class="tableblock">9%</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">The Rust Programming Language</p></td>
<td class="tableblock halign-center valign-top"><p class="tableblock">Done</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">Zero To Production In Rust</p></td>
<td class="tableblock halign-center valign-top"><p class="tableblock">Done</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">Ultimate Rust for Systems Programming</p></td>
<td class="tableblock halign-center valign-top"><p class="tableblock">39%</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">深入浅出 Rust</p></td>
<td class="tableblock halign-center valign-top"><p class="tableblock">Done</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">Rust 权威指南</p></td>
<td class="tableblock halign-center valign-top"><p class="tableblock">Done</p></td>
</tr>
</tbody>
</table>]]></content><author><name>ohmycloud</name></author><summary type="html"><![CDATA[Title Desc 精通 Rust（第2版） Done Black Hat Rust 34% Code Like a Pro in Rust Done Learn Rust in a Month of Lunches Done Rust in Action 1% Rust Servers Services and Apps 4% Rust Web Development 41% Mastering Rust Programming 26% Command-Line Rust Done Programming Rust Done Rust Atomics 15% Programming with Rust 15% Rust for the IoT 9% The Rust Programming Language Done Zero To Production In Rust Done Ultimate Rust for Systems Programming 39% 深入浅出 Rust Done Rust 权威指南 Done]]></summary></entry><entry><title type="html">Environment Variables &amp;amp; Rust</title><link href="https://ohmycloud.github.io/2024/03/07/environment-variables-and-rust.html" rel="alternate" type="text/html" title="Environment Variables &amp;amp; Rust" /><published>2024-03-07T00:00:00+00:00</published><updated>2024-03-07T00:00:00+00:00</updated><id>https://ohmycloud.github.io/2024/03/07/environment-variables-and-rust</id><content type="html" xml:base="https://ohmycloud.github.io/2024/03/07/environment-variables-and-rust.html"><![CDATA[<div class="paragraph">
<p>If you&#8217;ve ever worked on some kind of project you definitley have
encountered the need to declare some environment variables for it.</p>
</div>
<div class="paragraph">
<p>Environment variables are an easy way to setup essential parameters
that your program is going to use at runtime, i.e database URL, tracing level,
production or local environment.</p>
</div>
<div class="paragraph">
<p>In Rust you have multiple ways to make use of them</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-rust" data-lang="rust">use axum::{response::Html, routing::get, Router};

#[tokio::main]
async fn main() {
    // let's get our database
    let db_connection_str = std::env::var("DATABASE_URL")
        .expect("cannot find DATABASE_URL env");

    let pool = PgPoolOptions::new()
        .max_connections(5)
        .acquire_timeout(Duration::from_secs(3))
        .connect(&amp;db_connection_str)
        .await
        .expect("can't connect to database");

    let app = Router::new().route("/", get(handler)).with_state(pool);
    let listener = tokio::net::TcpListener::bind("127.0.0.1:3000")
        .await
        .unwrap();
    println!("listening on {}", listener.local_addr().unwrap());
    axum::serve(listener, app).await.unwrap();
}

async fn handler() -&gt; Html&lt;&amp;'static str&gt; {
    Html("&lt;h1&gt;Hello, World!&lt;/h1&gt;")
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>With the example above, the program expects to find <code>DATABASE_URL</code> in the process environment variables.
To make it work you&#8217;d have to run</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-shell session" data-lang="shell session">$ export DATABASE_URL="postgres://postgres:password@localhost"
$ cargo run</code></pre>
</div>
</div>
<div class="paragraph">
<p>Or you could use a simple one liner</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-shell session" data-lang="shell session">DATABASE_URL="postgres://postgres:password@localhost" cargo run</code></pre>
</div>
</div>
<div class="paragraph">
<p>Both of these will run the program okay, but there are some issues you might want to look out for:</p>
</div>
<div class="olist arabic">
<ol class="arabic">
<li>
<p>The command/s above are now stored in your <code>~/.[zsh|bash|fish]_history</code> file
now, in plaintext, and that&#8217;s bad, especially when you type out the
production database password</p>
</li>
<li>
<p>You have to type that everytime you are in a new shell session, that&#8217;s
especially bad if you have a terrible shell config without autocompletion and
suggestions (please, do yourself a favor and fix that)</p>
</li>
</ol>
</div>
        <div class="dialog matt" title="Matt">
          <div class="dialog-head" aria-hidden="true">
          <?xml version="1.0" encoding="utf-8"?>
<!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
<svg width="800px" height="800px" viewBox="0 0 1024 1024" class="icon"  version="1.1" xmlns="http://www.w3.org/2000/svg">
<path d="M419.847493 691.537171c-21.246751-16.838556-32.495766-40.218224-33.494791-61.035395-1.478556-30.8224 5.64199-66.562498 21.361639-107.222791a62.184273 62.184273 0 0 1 5.49963-0.824195c39.783649-4.183415 76.008273 30.237971 80.910985 76.879922 4.900215 46.641951-23.374673 87.841717-63.155824 92.022634a62.578888 62.578888 0 0 1-11.121639 0.179825z" fill="#FFFFFF" /><path d="M427.09042 771.746341h25.327765a24.97561 24.97561 0 0 0 23.297249-15.971902l35.61522-92.147512c0.504507-1.301229 0.896624-2.647415 1.176351-4.016078 2.75481-13.514302-5.969171-26.703922-19.485971-29.458732l-44.818732-9.138576-0.472039-0.089912c-13.566751-2.492566-26.586537 6.483668-29.079102 20.047922l-15.744624 85.666342-36.074771 6.87079A21.129366 21.129366 0 0 0 349.658537 754.263415a17.482927 17.482927 0 0 0 17.482926 17.482926h59.948957z" fill="#5DE4C7" /><path d="M396.462829 720.239141l14.81803-80.61877c3.241834-17.637776 20.165307-29.30638 37.803082-26.064547l0.6144 0.117386 44.82123 9.136078c17.570341 3.581502 28.911766 20.727259 25.332761 38.2976a33.010263 33.010263 0 0 1-1.528508 5.2224l-35.620214 92.15001A32.475785 32.475785 0 0 1 452.418185 779.239024H367.141463c-13.794029 0-24.97561-11.184078-24.975609-24.975609 0-13.74158 9.765463-25.545054 23.26478-28.115044l31.032195-5.90923zM452.418185 764.253659a17.477932 17.477932 0 0 0 16.306576-11.181581l35.617717-92.147512a17.482927 17.482927 0 0 0-12.814985-23.434615l-44.82123-9.131083c-9.827902-1.810732-18.939005 4.473132-20.687297 13.968859l-16.67122 90.711414-41.112351 7.829854A13.636683 13.636683 0 0 0 357.15122 754.263415a9.990244 9.990244 0 0 0 9.990243 9.990244h85.276722z" fill="#524F75" /><path d="M358.649756 761.526322l15.330029-3.873717a7.492683 7.492683 0 0 0-3.673912-14.53081l-15.330029 3.876215a7.492683 7.492683 0 1 0 3.673912 14.528312z" fill="#524F75" /><path d="M536.97561 771.746341h22.088429a24.97561 24.97561 0 0 0 24.878205-22.780253l5.254868-59.546849a25.00558 25.00558 0 0 0-1.463571-10.876878c-4.795317-12.932371-19.166283-19.528429-32.098653-14.73561l-32.33842 11.988293a24.973112 24.973112 0 0 0-16.29159 23.417132v29.004175l-27.782868 5.292332A21.129366 21.129366 0 0 0 462.04878 754.263415a17.482927 17.482927 0 0 0 17.482927 17.482926h57.443903z" fill="#5DE4C7" /><path d="M499.512195 722.017405v-22.805229c0-13.579239 8.449249-25.724878 21.179317-30.442771l32.335922-11.988293c16.81358-6.233912 35.497834 2.342712 41.729249 19.15879 1.675863 4.51559 2.325229 9.343376 1.903141 14.138693l-5.254868 59.546849A32.468293 32.468293 0 0 1 559.064039 779.239024H479.531707c-13.794029 0-24.97561-11.184078-24.975609-24.975609 0-13.74158 9.765463-25.545054 23.26478-28.115044l21.691317-4.130966zM559.064039 764.253659a17.482927 17.482927 0 0 0 17.415493-15.946927l5.25237-59.546849a17.482927 17.482927 0 0 0-23.492058-17.92999l-32.333424 11.988292a17.482927 17.482927 0 0 0-11.408859 16.393991v35.205619l-33.871922 6.4512A13.636683 13.636683 0 0 0 469.541463 754.263415a9.990244 9.990244 0 0 0 9.990244 9.990244h79.532332z" fill="#524F75" /><path d="M471.04 761.526322l15.330029-3.873717a7.492683 7.492683 0 0 0-3.673912-14.53081l-15.330029 3.876215a7.492683 7.492683 0 1 0 3.673912 14.528312z" fill="#524F75" /><path d="M273.123278 545.627161l2.777288 17.375532a24.978107 24.978107 0 0 0 20.754732 20.724761c7.325346 1.161366 12.8 1.630907 16.428956 1.411122 5.434693-0.329678 13.139668-3.241834 23.112429-8.736469a7.48519 7.48519 0 0 0 3.868722-6.888273l-0.207298-4.742868c19.106341 3.254322 36.152195 5.691941 51.137561 7.317854 17.378029 1.888156 45.238322 9.470751 83.583376 22.750282a7.492683 7.492683 0 0 0 9.945288-7.078087v-78.420917a7.492683 7.492683 0 0 0-8.356839-7.442732l-141.941386 16.488897-9.510712-3.18439-0.719297-12.417873a11.718556 11.718556 0 0 0-11.698576-11.03922 12.802498 12.802498 0 0 0-12.667629 10.939318l-1.8432 12.515278c-2.152898 0-4.240859 0.269737-6.23641 0.779239l-34.890927 1.735805a13.719102 13.719102 0 0 0-13.037268 13.699121 13.576741 13.576741 0 0 0 13.042263 13.566752l16.458927 0.646868z" fill="#5DE4C7" /><path d="M256.372137 552.46798a21.069424 21.069424 0 0 1-20.240235-21.054439 21.211785 21.211785 0 0 1 20.157815-21.184312l34.19161-1.700839c0.247259-0.054946 0.49202-0.109893 0.739278-0.159844l0.996527-6.77838a20.297678 20.297678 0 0 1 20.08039-17.340566 19.211239 19.211239 0 0 1 19.178771 18.097327l0.427083 7.355317 3.119453 1.04398 140.283005-16.294087a14.985366 14.985366 0 0 1 16.713678 14.885463v78.420917a14.985366 14.985366 0 0 1-19.890575 14.158673c-37.848039-13.109698-65.266263-20.57241-81.939981-22.383141-12.88242-1.396137-27.245893-3.384195-43.092917-5.966673a14.977873 14.977873 0 0 1-7.282888 9.395824c-10.86439 5.984156-19.473483 9.238478-26.276839 9.653073-4.288312 0.259746-10.237502-0.254751-18.054868-1.493541a32.468293 32.468293 0 0 1-26.981151-26.941191l-1.808234-11.311453-10.319922-0.402108z m76.003278 12.627669a7.492683 7.492683 0 0 1 8.741463-7.712469c18.96398 3.231844 35.862478 5.649483 50.688 7.255415 18.082341 1.963083 46.3872 9.668059 85.229268 23.12242v-78.420917l-141.941385 16.4864a7.432741 7.432741 0 0 1-3.241834-0.339669l-9.510712-3.179395a7.49518 7.49518 0 0 1-5.102517-6.673483l-0.721796-12.417873a4.225873 4.225873 0 0 0-4.21838-3.981112c-2.634927 0-4.870244 1.930615-5.254868 4.538068l-1.840703 12.520273a7.490185 7.490185 0 0 1-7.412761 6.398752c-1.498537 0-2.967102 0.18482-4.385717 0.546965-0.484527 0.124878-0.979044 0.199805-1.478556 0.224781l-34.893424 1.733307a6.223922 6.223922 0 0 0-5.916722 6.216429 6.081561 6.081561 0 0 0 5.844292 6.079064l16.458927 0.649366a7.490185 7.490185 0 0 1 7.105561 6.301346l2.777288 17.375532a17.487922 17.487922 0 0 0 14.528312 14.508331c6.830829 1.083941 11.835941 1.511024 14.803044 1.3312 4.071024-0.244761 10.869385-2.814751 19.94802-7.817365l-0.2048-4.745366z" fill="#524F75" /><path d="M273.29561 553.449522h19.985483a7.492683 7.492683 0 1 0 0-14.985366h-19.985483a7.492683 7.492683 0 0 0 0 14.985366z" fill="#524F75" /><path d="M582.815844 294.51239c5.452176 10.699551-7.530146 31.142088-38.939473 61.32761l-32.490771-63.772722c42.171317-9.068644 65.980566-8.254439 71.430244 2.445112z" fill="#FFC48B" /><path d="M576.541971 298.640859c-2.632429-5.64199-20.832156-7.370302-53.5552-2.332722l21.761249 46.664429c24.343727-22.915122 34.481327-38.564839 31.793951-44.331707z m13.579239-6.331318c7.200468 15.439922-7.692488 37.178693-42.843161 68.677932a7.492683 7.492683 0 0 1-11.790986-2.412644l-30.247961-64.866653a7.492683 7.492683 0 0 1 5.472157-10.542205c46.127454-8.249444 72.139551-6.448702 79.409951 9.14357z" fill="#524F75" /><path d="M600.181385 355.700137c4.775337 9.790439-7.322849 28.130029-36.292058 55.016273l-28.462205-58.365503c38.392507-7.55762 59.978927-6.44121 64.754263 3.34923z" fill="#FFC48B" /><path d="M562.653034 396.919883c11.381385-8.689015 19.810654-16.266615 25.247844-22.652878 5.577054-6.5536 7.330341-10.979278 6.643512-12.974829-0.661854-1.915629-4.600507-4.140956-12.839961-5.589542-8.154537-1.431102-19.398556-1.835707-33.649639-1.176351l14.598244 42.3936z m46.06002-40.507942c5.184937 15.055298-10.442302 33.407376-45.420644 58.695181a7.492683 7.492683 0 0 1-11.473795-3.633951l-21.141854-61.397542a7.492683 7.492683 0 0 1 6.541112-9.912819c42.750751-3.09198 66.257795 1.03399 71.495181 16.249131z" fill="#524F75" /><path d="M614.117776 421.291083c3.546537 10.302439-10.697054 27.028605-42.725776 50.183493l-21.141854-61.397542c39.029385-2.824741 60.321093 0.914107 63.86763 11.214049z" fill="#FFC48B" /><path d="M599.547005 438.426849c6.436215-5.711922 8.78642-9.85038 8.384312-11.923356-0.387122-1.988059-3.981112-4.740371-11.935844-7.320352-7.872312-2.552507-18.951493-4.518088-33.157619-5.849287l8.556644 44.014517c12.475317-7.020644 21.878634-13.351961 28.152507-18.921522z m23.092449-14.783064c3.039532 15.629737-14.990361 31.63161-53.1456 51.80441a7.49518 7.49518 0 0 1-10.859395-5.194927l-12.3904-63.742751a7.492683 7.492683 0 0 1 7.857326-8.903805c42.763239 2.884683 65.468566 10.242498 68.538069 26.037073z" fill="#524F75" /><path d="M622.177405 470.490537c5.53959 8.863844-3.067005 26.888741-25.812293 54.069697l-33.015258-52.830907c33.67961-9.690537 53.287961-10.102634 58.827551-1.23879z" fill="#FFC48B" /><path d="M613.203668 487.011902c3.069502-7.048117 3.404176-11.343922 2.250303-13.054751-1.103922-1.6384-5.00761-2.799766-12.437854-2.385171-7.165502 0.402107-16.606283 2.285268-28.242419 5.664469l23.324722 34.578731c7.160507-9.827902 12.198088-18.122302 15.105248-24.803278z m14.673171-21.43157c8.556644 12.680117-0.31719 33.067707-24.208859 63.735258a7.49518 7.49518 0 0 1-12.12316-0.414595l-34.838479-51.649561a7.492683 7.492683 0 0 1 3.893698-11.313951c36.664195-11.950829 58.630244-13.179629 67.2768-0.357151z" fill="#524F75" /><path d="M651.308956 502.14962c8.206985 4.930185 8.679024 23.219824 1.416117 54.866419l-48.912234-29.391298c23.45959-21.916098 39.289132-30.407805 47.496117-25.475121z" fill="#FFC48B" /><path d="M650.419824 520.112078c0.057444-6.848312-1.1264-10.394849-2.48757-11.281483-1.291239-0.836683-4.782829-0.444566-10.72203 2.480078-5.696937 2.804761-12.720078 7.562615-20.992 14.261073l30.560156 19.84562c2.372683-10.404839 3.581502-18.864078 3.641444-25.305288z m5.671961-23.846712c12.09319 7.852332 11.908371 28.409756 2.6624 63.093385a7.492683 7.492683 0 0 1-11.321444 4.353249l-47.858263-31.077151a7.490185 7.490185 0 0 1-0.83918-11.933347c26.861268-23.394654 45.123434-32.380878 57.356487-24.436136z" fill="#524F75" /><path d="M699.946459 502.511766c8.861346 1.088937 16.19918 16.488898 22.018497 46.204878l-52.820917-6.486166c11.6736-27.568078 21.938576-40.807649 30.80242-39.718712z" fill="#FFC48B" /><path d="M705.121405 517.85678c-2.87719-5.5296-5.284839-7.814868-6.583571-7.929756-0.369639-0.032468-0.966556 0.152351-1.950595 0.826693-1.540995 1.056468-3.356722 2.952117-5.339785 5.699434-3.356722 4.657951-6.945717 11.403863-10.714537 20.197776l32.44082 2.839727c-2.535024-9.240976-5.167454-16.468917-7.852332-21.633874z m-5.277346-22.860175c13.7216 1.201327 22.637893 18.344585 30.267941 51.177522a7.49518 7.49518 0 0 1-7.954732 9.161053l-53.018224-4.63797a7.492683 7.492683 0 0 1-6.343805-10.142595c11.963317-31.244488 23.159883-46.771824 37.04882-45.55801z" fill="#524F75" /><path d="M356.821541 272.883512c29.793405-12.213073 63.970029-15.185171 103.206713 0s84.415063 80.036839 99.879961 138.272468c4.735376 17.832585 7.035629 34.588722 6.900761 50.270908-0.41959 48.003122 35.894946 88.373698 83.673287 93.016663 17.313093 1.683356 62.736234-13.863961 94.442771-42.103883 11.174088-12.907395 18.187239-18.666771 21.046946-17.275629 4.285815 2.085463 1.301229 15.737132 0.796722 17.275629-16.59879 50.805385-31.686556 68.740371-50.842848 85.743766s-41.112351 32.418341-65.443591 42.770732c-9.765463 27.533112-49.099551 52.406322-80.341541 62.344117s-57.771083 14.01881-103.386537 8.354341-78.588254-43.162849-80.40398-81.048351c-1.933112-40.308137 10.379863-88.238829 36.941424-143.794575a7.487688 7.487688 0 0 0-6.089053-10.694557c-52.993249-4.765346-85.341659-11.481288-97.042732-20.150321C293.798088 436.328898 284.721951 408.813268 284.721951 374.436839c0-49.299356 42.306185-89.342751 72.09959-101.553327z" fill="#5DE4C7" /><path d="M356.821541 272.883512C327.028137 285.094088 284.721951 325.137483 284.721951 374.436839c0 34.376429 9.076137 61.892059 35.437893 81.425483 11.701073 8.669034 44.049483 15.387473 97.042732 20.150322a7.492683 7.492683 0 0 1 6.089053 10.694556c-26.561561 55.555746-38.874537 103.488937-36.941424 143.794576 1.818224 37.885502 34.791024 75.383883 80.40398 81.048351s72.144546 1.583454 103.386537-8.354342 70.576078-34.811005 80.341541-62.344117c24.331239-10.35239 46.2848-25.767337 65.443591-42.770731s34.246556-34.93838 50.842848-85.743766c0.50201-1.538498 3.486595-15.190166-0.796722-17.27563-2.859707-1.391141-9.872859 4.368234-21.046946 17.27563-31.706537 28.24242-77.132176 43.787239-94.442771 42.103883-47.778341-4.642966-84.092878-45.013541-83.673287-93.016664 0.137366-15.682185-2.165385-32.438322-6.900761-50.270907-15.464898-58.233132-60.643278-123.0848-99.879961-138.269971s-73.413307-12.213073-103.206713 0z m392.239454 213.873639c2.709854-2.225327 5.259863-3.921171 7.924761-5.100019 4.877737-2.157893 10.145093-2.694868 15.54482-0.067434 6.084059 2.95961 8.993717 8.074615 10.14759 13.93639 0.589424 2.987083 0.674341 6.086556 0.439571 9.438283-0.3072 4.315785-1.258771 9.450771-2.102947 12.028253-15.454907 47.313795-29.710985 69.731902-55.141151 92.299864-20.395083 18.097327-41.674302 32.615649-63.91758 42.865639-13.566751 27.902751-50.171005 53.520234-87.272274 65.318712-36.759102 11.69358-65.503532 14.443395-109.775297 8.943766-51.112585-6.3488-91.278361-48.34279-93.526166-95.202029-1.950595-40.665288 9.435785-87.706849 33.864429-141.287025-49.686478-4.957659-80.146732-11.761015-94.008195-22.030985-29.021659-21.501502-41.501971-52.044176-41.501971-93.463727 0-26.544078 10.394849-52.059161 28.207454-74.102634 15.07278-18.654283 34.870946-33.806985 53.193054-41.317151 36.159688-14.823024 74.162576-15.644722 114.300878-0.109893 43.60242 16.87602 92.035122 84.697288 108.956097 148.402576 5.067551 19.081366 7.547629 37.163707 7.400273 54.249522-0.352156 40.235707 30.090615 74.075161 70.139005 77.971356 15.659707 1.521015 56.764566-15.35001 82.332098-37.763122 5.796839-6.656 10.662088-11.618654 14.795551-15.010342z" fill="#524F75" /><path d="M312.195122 392.117073a7.492683 7.492683 0 0 1 7.492683 7.492683v14.985366a7.492683 7.492683 0 1 1-14.985366 0v-14.985366a7.492683 7.492683 0 0 1 7.492683-7.492683zM347.160976 392.117073a7.492683 7.492683 0 0 1 7.492683 7.492683v14.985366a7.492683 7.492683 0 1 1-14.985366 0v-14.985366a7.492683 7.492683 0 0 1 7.492683-7.492683z" fill="#44756A" /><path d="M405.069424 489.951532c10.911844 1.138888 19.840624 1.138888 26.891239-0.064937 21.561444-3.688898 28.309854-6.211434 41.364605-17.313093a7.492683 7.492683 0 1 0-9.708019-11.416351c-10.619629 9.03118-15.035317 10.679571-34.186615 13.956371-5.50962 0.94158-13.144663 0.94158-22.807727-0.067434a7.492683 7.492683 0 1 0-1.553483 14.905444z" fill="#524F75" /><path d="M419.847493 691.537171c-21.246751-16.838556-32.498263-40.218224-33.497288-61.035395-1.476059-30.8224 5.64199-66.562498 21.361639-107.220293a62.184273 62.184273 0 0 1 5.499629-0.824195c39.783649-4.183415 76.008273 30.237971 80.910986 76.879922 4.900215 46.641951-23.374673 87.841717-63.155825 92.022634-3.746341 0.392117-7.460215 0.444566-11.119141 0.177327z" fill="#FFFFFF" /><path d="M404.689795 261.144976L364.024507 257.973073C383.77522 213.926088 415.264468 195.391688 458.484761 202.369873 501.707551 209.345561 521.920312 239.293815 519.120546 292.214634H463.514849c-0.574439-33.819473-8.117073-52.533698-22.632898-56.147668-14.515824-3.611473-26.579044 4.745366-36.192156 25.07801z" fill="#FFF185" /><path d="M442.690185 228.796566c17.645268 4.390712 26.444176 23.519532 28.072586 55.925385H511.875122C512.449561 239.935688 494.517073 215.774283 457.290927 209.765151 420.821541 203.880898 394.020215 217.3952 375.625678 251.362029l24.640937 1.923122c10.759493-19.953015 25.145444-28.789385 42.42357-24.488585zM352.832937 264.614088l4.353248-9.70802C378.283083 207.867005 412.98919 187.436956 459.678595 194.972098 506.979902 202.607141 529.590322 236.111922 526.600741 292.611746L526.22361 299.707317H456.147044l-0.124878-7.365307c-0.52199-30.759961-6.863298-46.492098-16.950946-49.004644-10.459785-2.602459-19.358595 3.561522-27.605542 21.009483l-2.207844 4.670439L352.832937 264.614088z" fill="#524F75" /><path d="M499.512195 304.702439m-47.453658 0a47.453659 47.453659 0 1 0 94.907317 0 47.453659 47.453659 0 1 0-94.907317 0Z" fill="#FFF185" /><path d="M499.512195 359.64878c-30.345366 0-54.946341-24.600976-54.946341-54.946341s24.600976-54.946341 54.946341-54.946341 54.946341 24.600976 54.946342 54.946341-24.600976 54.946341-54.946342 54.946341z m0-14.985365c22.068449 0 39.960976-17.892527 39.960976-39.960976s-17.892527-39.960976-39.960976-39.960976-39.960976 17.892527-39.960975 39.960976 17.892527 39.960976 39.960975 39.960976z" fill="#524F75" /><path d="M507.004878 297.209756m-24.97561 0a24.97561 24.97561 0 1 0 49.95122 0 24.97561 24.97561 0 1 0-49.95122 0Z" fill="#FFFBDC" /><path d="M312.195122 302.204878m-37.463415 0a37.463415 37.463415 0 1 0 74.92683 0 37.463415 37.463415 0 1 0-74.92683 0Z" fill="#FFFFFF" /><path d="M312.195122 347.160976C287.366868 347.160976 267.239024 327.033132 267.239024 302.204878S287.366868 257.24878 312.195122 257.24878s44.956098 20.127844 44.956098 44.956098-20.127844 44.956098-44.956098 44.956098z m0-14.985366c16.551337 0 29.970732-13.419395 29.970732-29.970732S328.746459 272.234146 312.195122 272.234146 282.22439 285.653541 282.22439 302.204878s13.419395 29.970732 29.970732 29.970732z" fill="#524F75" /><path d="M292.446907 310.798985A11.239024 11.239024 0 1 0 289.717073 303.22638l8.331864 1.211318-5.60203 6.361287z" fill="#232323" /><path d="M498.458224 472.543532c7.662517-16.416468 12.495298-30.342868 14.498342-41.781698 1.153873-19.381073 1.153873-32.445815 0-39.194224-0.3072-1.790751-2.497561-4.810302-6.571083-9.058654-13.621698-3.711376-22.528-17.178224-20.235239-31.431805C488.987473 333.431883 504.762068 320.826693 522.599649 321.950595l21.511492 1.356176c15.464898 0.976546 27.732917 12.879922 29.558635 27.850302 4.770341 2.769795 9.588137 7.442732 9.448273 13.389425-0.304702 13.002302-8.569132 18.269659-18.11481 19.615843l-13.444371 1.893152 7.357815 35.273053c1.940605 11.853424 6.086556 23.487063 6.086556 38.122771l-6.086556 45.655415" fill="#5DE4C7" /><path d="M552.273171 426.650849c0.279727 1.41362 0.589424 2.882185 0.976546 4.62798 0.147356 0.674341 0.299707 1.358673 0.507005 2.280273l0.507005 2.265288c2.282771 10.23001 3.204371 16.131746 3.246829 23.139903l-6.016624 45.153405a7.492683 7.492683 0 1 0 14.852995 1.978068l6.084058-45.655415c0.044956-0.32718 0.067434-0.659356 0.067435-0.989034 0-8.59161-1.048976-15.429932-3.608976-26.891239l-0.509503-2.277776-0.494517-2.225326a184.817015 184.817015 0 0 1-0.909112-4.318283 124.42599 124.42599 0 0 1-0.661853-3.621464l-5.779357-27.757892 5.517113-0.776742c14.513327-2.043005 24.196371-11.179083 24.561014-26.858771 0.172332-7.387785-3.88121-13.546771-10.107629-18.054868A39.30162 39.30162 0 0 0 544.585678 315.831571l-21.511493-1.356176C501.382868 313.104234 482.2016 328.431766 478.752468 349.888312c-2.762302 17.195707 7.357815 33.67961 23.527025 39.196722 1.176351 1.286244 2.092956 2.385171 2.739824 3.2768 0.284722 0.392117 0.494517 0.714302 0.629385 0.949073 0.94158 6.13401 0.9216 18.474459-0.144858 36.574283-1.920624 10.634615-6.521132 23.829229-13.83399 39.491434a7.492683 7.492683 0 0 0 13.576741 6.341308c7.919766-16.963434 12.959844-31.486751 15.090264-43.657366 0.049951-0.279727 0.08242-0.561951 0.099902-0.846673 1.188839-19.940527 1.188839-33.409873-0.094907-40.902556-0.654361-3.826263-3.404176-7.620059-8.546654-12.982322a7.500176 7.500176 0 0 0-3.436644-2.043005c-10.037698-2.734829-16.473912-12.652644-14.808039-23.015025a27.208429 27.208429 0 0 1 28.577093-22.837697l21.511492 1.356175a24.311259 24.311259 0 0 1 22.595435 21.27922 7.48519 7.48519 0 0 0 3.673912 5.572058c3.69639 2.145405 5.766868 4.767844 5.721912 6.733425-0.179824 7.739941-3.941151 11.28398-11.671102 12.372917l-13.441874 1.893151a7.492683 7.492683 0 0 0-6.291356 8.948761l7.325347 35.118205c0.209795 1.261268 0.449561 2.562498 0.721795 3.943649z" fill="#524F75" /><path d="M555.707317 528.234146m-8.741463 0a8.741463 8.741463 0 1 0 17.482926 0 8.741463 8.741463 0 1 0-17.482926 0Z" fill="#524F75" /><path d="M514.05799 326.683473l-2.340214 15.764605a7.492683 7.492683 0 1 0 14.820526 2.200351l2.342713-15.764605a7.492683 7.492683 0 0 0-14.823025-2.200351zM539.0336 329.181034l-2.340215 15.764605a7.492683 7.492683 0 1 0 14.820527 2.200351l2.342712-15.764605a7.492683 7.492683 0 0 0-14.823024-2.200351z" fill="#524F75" /><path d="M389.619512 289.717073m-47.453658 0a47.453659 47.453659 0 1 0 94.907317 0 47.453659 47.453659 0 1 0-94.907317 0Z" fill="#FFFFFF" /><path d="M389.619512 344.663415C359.274146 344.663415 334.673171 320.062439 334.673171 289.717073S359.274146 234.770732 389.619512 234.770732s54.946341 24.600976 54.946342 54.946341-24.600976 54.946341-54.946342 54.946342z m0-14.985366c22.068449 0 39.960976-17.892527 39.960976-39.960976S411.687961 249.756098 389.619512 249.756098 349.658537 267.648624 349.658537 289.717073s17.892527 39.960976 39.960975 39.960976z" fill="#524F75" /><path d="M365.787785 302.007571A14.985366 14.985366 0 1 0 362.146341 291.909932l11.109152 1.615922-7.467708 8.481717z" fill="#232323" />
</svg>

          </div>
          <div class="dialog-text">
          <p>Come on... everybody uses .env files nowadays!</p>
          </div>
        </div>
<div class="paragraph">
<p>I know, I know, you already know all that, it&#8217;s basic software dev stuff after all.</p>
</div>
<div class="paragraph">
<p>In order to not leak sensitive data, we can use a
<code>.env</code> file in the project&#8217;s folder (I&#8217;ll talk about how I F-up with those
files one day). There&#8217;s a pretty common crate in Rust to read environment variables
at runtime and that&#8217;s <a href="https://github.com/dotenv-rs/dotenv/tree/master"><code>dotenv</code></a>.</p>
</div>
<div class="paragraph">
<p><code>dotenv</code> will check if you have a <code>.env</code> file in your project&#8217;s folder and
<em>load</em> the env variables in there for you. Here&#8217;s how the whole thing would look like:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-shell session" data-lang="shell session">$ cat .env
DATABASE_URL="postgres://postgres:password@localhost"</code></pre>
</div>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-rust" data-lang="rust">use dotenv::dotenv;
use axum::{response::Html, routing::get, Router};

#[tokio::main]
async fn main() {
    // load environments from .env
    dotenv().ok();

    // let's get our database
    let db_connection_str = std::env::var("DATABASE_URL")
        .expect("cannot find DATABASE_URL env");

    let pool = PgPoolOptions::new()
        .max_connections(5)
        .acquire_timeout(Duration::from_secs(3))
        .connect(&amp;db_connection_str)
        .await
        .expect("can't connect to database");

    let app = Router::new().route("/", get(handler)).with_state(pool);
    let listener = tokio::net::TcpListener::bind("127.0.0.1:3000")
        .await
        .unwrap();
    println!("listening on {}", listener.local_addr().unwrap());
    axum::serve(listener, app).await.unwrap();
}

async fn handler() -&gt; Html&lt;&amp;'static str&gt; {
    Html("&lt;h1&gt;Hello, World!&lt;/h1&gt;")
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>I see <code>dotenv</code> used all over the place, but there&#8217;s another way to achieve the
same without the <code>.env</code> file.</p>
</div>
<div class="paragraph">
<p>Since Cargo 1.56 you can use <a href="https://doc.rust-lang.org/nightly/cargo/reference/config.html#env">configurable-env</a></p>
</div>
<div class="quoteblock">
<blockquote>
<div class="paragraph">
<p>The [env] section allows you to set additional environment variables for build
scripts, rustc invocations, cargo run and cargo build.</p>
</div>
</blockquote>
</div>
<div class="paragraph">
<p>I prefer this method to the <code>dotenv</code> one because it does pretty much the same
and the environment variables are set by <code>cargo</code> itself instead of the program
runtime. Also, most of my deployments don&#8217;t have a <code>.env</code> file to parse, but I
just set environment variables in the container itself or in the parent process
and this approach better simulates that kind of setup.</p>
</div>
<div class="paragraph">
<p>Let&#8217;s get rid of <code>dotenv</code> and use <code>.cargo/config.toml</code></p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-shell session" data-lang="shell session">$ rm .env
$ cat .cargo/config.toml
[env]
DATABASE_URL="postgres://postgres:password@localhost"</code></pre>
</div>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-rust" data-lang="rust">use axum::{response::Html, routing::get, Router};

#[tokio::main]
async fn main() {
    // it's the same as the first iteration, if you don't find
    // differences it's because there's none :)

    // let's get our database
    let db_connection_str = std::env::var("DATABASE_URL")
        .expect("cannot find DATABASE_URL env");

    let pool = PgPoolOptions::new()
        .max_connections(5)
        .acquire_timeout(Duration::from_secs(3))
        .connect(&amp;db_connection_str)
        .await
        .expect("can't connect to database");

    let app = Router::new().route("/", get(handler)).with_state(pool);
    let listener = tokio::net::TcpListener::bind("127.0.0.1:3000")
        .await
        .unwrap();
    println!("listening on {}", listener.local_addr().unwrap());
    axum::serve(listener, app).await.unwrap();
}

async fn handler() -&gt; Html&lt;&amp;'static str&gt; {
    Html("&lt;h1&gt;Hello, World!&lt;/h1&gt;")
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>Much neater, and we removed a crate from the project dependencies. But we&#8217;re not
done yet, there&#8217;s another scenario that we&#8217;ve not yet talked about.</p>
</div>
<div class="paragraph">
<p>Up until now we&#8217;ve only covered environment variables that won&#8217;t change
frequently, that is the reason why we can easily create a file and write them
there and we&#8217;d be okay forever. What if we need environment variables that need
to change very frequently? Or that depend on complex logic? Or some command?</p>
</div>
<div class="paragraph">
<p>It&#8217;s common in a lot of open source programs to see their commit hash somewhere
to indicate that the version that you&#8217;re currently using is the one that has
that HEAD commit. How would you do that in Rust?</p>
</div>
<div class="paragraph">
<p>Well, turns out that it&#8217;s easily achievable with the <code>build.rs</code> file.</p>
</div>
<div class="quoteblock">
<blockquote>
<div class="paragraph">
<p>Placing a file named build.rs in the root of a package will cause Cargo to
compile that script and execute it just before building the package.</p>
</div>
</blockquote>
</div>
<div class="paragraph">
<p>Within <code>build.rs</code> we can provide whatever environment variable we want to
the <code>rustc</code> compiler by using <code>println!("cargo:rustc-env=&#8230;&#8203;")</code>, that way we can
expose that value into our project at compiletime.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-rust" data-lang="rust">// [build.rs]
fn main() {
    set_revision_hash();
}

// pass the result of `git rev-parse --short=10 HEAD` to rustc
fn set_revision_hash() {
    use std::process::Command;

    let args = &amp;["rev-parse", "--short=10", "HEAD"];
    let Ok(output) = Command::new("git").args(args).output() else {
        return;
    };

    let rev = String::from_utf8_lossy(&amp;output.stdout).trim().to_string();
    if rev.is_empty() {
        return;
    }

    println!("cargo:rustc-env=BUILD_GIT_HASH={}", rev);
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>With that in place we can make use <code>BUILD_GIT_HASH</code> in our program</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-rust" data-lang="rust">use axum::{response::Html, routing::get, Router};

#[tokio::main]
async fn main() {
    // let's get our database
    let db_connection_str = std::env::var("DATABASE_URL")
        .expect("cannot find DATABASE_URL env");

    let pool = PgPoolOptions::new()
        .max_connections(5)
        .acquire_timeout(Duration::from_secs(3))
        .connect(&amp;db_connection_str)
        .await
        .expect("can't connect to database");

    let app = Router::new()
        .route("/", get(handler))
        // here we can now take that environment
        // at compiletime with env!()
        .route("/_meta", get(|| async { env!("BUILD_GIT_HASH") }))
        .with_state(pool);

    let listener = tokio::net::TcpListener::bind("127.0.0.1:3000")
        .await
        .unwrap();

    println!("listening on {}", listener.local_addr().unwrap());
    axum::serve(listener, app).await.unwrap();
}

async fn handler() -&gt; Html&lt;&amp;'static str&gt; {
    Html("&lt;h1&gt;Welcome!&lt;/h1&gt;")
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>Notice that this time I&#8217;ve used the <code>env!</code> macro, which takes environment
variables at <strong>compiletime</strong> and not at <strong>runtime</strong>, big difference there!</p>
</div>
<div class="paragraph">
<p>I&#8217;m sure there are other infinite ways to do what I&#8217;ve explained above, but
these are the ones that I&#8217;ve seen used the most.</p>
</div>
<div class="paragraph">
<p>To be fair, I&#8217;ve been a <code>dotenv</code> guy for quite some time when I first started
with Rust, but I&#8217;ve discovered the <code>.cargo/config.toml</code> alternative recently
even though it&#8217;s been around for a long time, so I hope it&#8217;s something new for
you too.</p>
</div>]]></content><author><name>ohmycloud</name></author><summary type="html"><![CDATA[If you&#8217;ve ever worked on some kind of project you definitley have encountered the need to declare some environment variables for it.]]></summary></entry></feed>