Files
uutils.github.io/dev/src/uu_split/split.rs.html
T
2022-10-08 03:43:05 +00:00

2770 lines
182 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!DOCTYPE html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta name="generator" content="rustdoc"><meta name="description" content="Source of the Rust file `src/uu/split/src/split.rs`."><meta name="keywords" content="rust, rustlang, rust-lang"><title>split.rs - source</title><link rel="preload" as="font" type="font/woff2" crossorigin href="../../SourceSerif4-Regular.ttf.woff2"><link rel="preload" as="font" type="font/woff2" crossorigin href="../../FiraSans-Regular.woff2"><link rel="preload" as="font" type="font/woff2" crossorigin href="../../FiraSans-Medium.woff2"><link rel="preload" as="font" type="font/woff2" crossorigin href="../../SourceCodePro-Regular.ttf.woff2"><link rel="preload" as="font" type="font/woff2" crossorigin href="../../SourceSerif4-Bold.ttf.woff2"><link rel="preload" as="font" type="font/woff2" crossorigin href="../../SourceCodePro-Semibold.ttf.woff2"><link rel="stylesheet" type="text/css" href="../../normalize.css"><link rel="stylesheet" type="text/css" href="../../rustdoc.css" id="mainThemeStyle"><link rel="stylesheet" type="text/css" href="../../ayu.css" disabled><link rel="stylesheet" type="text/css" href="../../dark.css" disabled><link rel="stylesheet" type="text/css" href="../../light.css" id="themeStyle"><script id="default-settings" ></script><script src="../../storage.js"></script><script defer src="../../source-script.js"></script><script defer src="../../source-files.js"></script><script defer src="../../main.js"></script><noscript><link rel="stylesheet" href="../../noscript.css"></noscript><link rel="alternate icon" type="image/png" href="../../favicon-16x16.png"><link rel="alternate icon" type="image/png" href="../../favicon-32x32.png"><link rel="icon" type="image/svg+xml" href="../../favicon.svg"></head><body class="rustdoc source"><!--[if lte IE 11]><div class="warning">This old browser is unsupported and will most likely display funky things.</div><![endif]--><nav class="mobile-topbar"><button class="sidebar-menu-toggle">&#9776;</button><a class="sidebar-logo" href="../../uu_split/index.html"><div class="logo-container"><img class="rust-logo" src="../../rust-logo.svg" alt="logo"></div></a><h2 class="location"></h2></nav><nav class="sidebar"><a class="sidebar-logo" href="../../uu_split/index.html"><div class="logo-container"><img class="rust-logo" src="../../rust-logo.svg" alt="logo"></div></a></nav><main><div class="width-limiter"><div class="sub-container"><a class="sub-logo-container" href="../../uu_split/index.html"><img class="rust-logo" src="../../rust-logo.svg" alt="logo"></a><nav class="sub"><form class="search-form"><div class="search-container"><span></span><input class="search-input" name="search" autocomplete="off" spellcheck="false" placeholder="Click or press S to search, ? for more options…" type="search"><div id="help-button" title="help" tabindex="-1"><button type="button">?</button></div><div id="settings-menu" tabindex="-1"><a href="../../settings.html" title="settings"><img width="22" height="22" alt="Change settings" src="../../wheel.svg"></a></div></div></form></nav></div><section id="main-content" class="content"><div class="example-wrap"><pre class="line-numbers"><span id="1">1</span>
<span id="2">2</span>
<span id="3">3</span>
<span id="4">4</span>
<span id="5">5</span>
<span id="6">6</span>
<span id="7">7</span>
<span id="8">8</span>
<span id="9">9</span>
<span id="10">10</span>
<span id="11">11</span>
<span id="12">12</span>
<span id="13">13</span>
<span id="14">14</span>
<span id="15">15</span>
<span id="16">16</span>
<span id="17">17</span>
<span id="18">18</span>
<span id="19">19</span>
<span id="20">20</span>
<span id="21">21</span>
<span id="22">22</span>
<span id="23">23</span>
<span id="24">24</span>
<span id="25">25</span>
<span id="26">26</span>
<span id="27">27</span>
<span id="28">28</span>
<span id="29">29</span>
<span id="30">30</span>
<span id="31">31</span>
<span id="32">32</span>
<span id="33">33</span>
<span id="34">34</span>
<span id="35">35</span>
<span id="36">36</span>
<span id="37">37</span>
<span id="38">38</span>
<span id="39">39</span>
<span id="40">40</span>
<span id="41">41</span>
<span id="42">42</span>
<span id="43">43</span>
<span id="44">44</span>
<span id="45">45</span>
<span id="46">46</span>
<span id="47">47</span>
<span id="48">48</span>
<span id="49">49</span>
<span id="50">50</span>
<span id="51">51</span>
<span id="52">52</span>
<span id="53">53</span>
<span id="54">54</span>
<span id="55">55</span>
<span id="56">56</span>
<span id="57">57</span>
<span id="58">58</span>
<span id="59">59</span>
<span id="60">60</span>
<span id="61">61</span>
<span id="62">62</span>
<span id="63">63</span>
<span id="64">64</span>
<span id="65">65</span>
<span id="66">66</span>
<span id="67">67</span>
<span id="68">68</span>
<span id="69">69</span>
<span id="70">70</span>
<span id="71">71</span>
<span id="72">72</span>
<span id="73">73</span>
<span id="74">74</span>
<span id="75">75</span>
<span id="76">76</span>
<span id="77">77</span>
<span id="78">78</span>
<span id="79">79</span>
<span id="80">80</span>
<span id="81">81</span>
<span id="82">82</span>
<span id="83">83</span>
<span id="84">84</span>
<span id="85">85</span>
<span id="86">86</span>
<span id="87">87</span>
<span id="88">88</span>
<span id="89">89</span>
<span id="90">90</span>
<span id="91">91</span>
<span id="92">92</span>
<span id="93">93</span>
<span id="94">94</span>
<span id="95">95</span>
<span id="96">96</span>
<span id="97">97</span>
<span id="98">98</span>
<span id="99">99</span>
<span id="100">100</span>
<span id="101">101</span>
<span id="102">102</span>
<span id="103">103</span>
<span id="104">104</span>
<span id="105">105</span>
<span id="106">106</span>
<span id="107">107</span>
<span id="108">108</span>
<span id="109">109</span>
<span id="110">110</span>
<span id="111">111</span>
<span id="112">112</span>
<span id="113">113</span>
<span id="114">114</span>
<span id="115">115</span>
<span id="116">116</span>
<span id="117">117</span>
<span id="118">118</span>
<span id="119">119</span>
<span id="120">120</span>
<span id="121">121</span>
<span id="122">122</span>
<span id="123">123</span>
<span id="124">124</span>
<span id="125">125</span>
<span id="126">126</span>
<span id="127">127</span>
<span id="128">128</span>
<span id="129">129</span>
<span id="130">130</span>
<span id="131">131</span>
<span id="132">132</span>
<span id="133">133</span>
<span id="134">134</span>
<span id="135">135</span>
<span id="136">136</span>
<span id="137">137</span>
<span id="138">138</span>
<span id="139">139</span>
<span id="140">140</span>
<span id="141">141</span>
<span id="142">142</span>
<span id="143">143</span>
<span id="144">144</span>
<span id="145">145</span>
<span id="146">146</span>
<span id="147">147</span>
<span id="148">148</span>
<span id="149">149</span>
<span id="150">150</span>
<span id="151">151</span>
<span id="152">152</span>
<span id="153">153</span>
<span id="154">154</span>
<span id="155">155</span>
<span id="156">156</span>
<span id="157">157</span>
<span id="158">158</span>
<span id="159">159</span>
<span id="160">160</span>
<span id="161">161</span>
<span id="162">162</span>
<span id="163">163</span>
<span id="164">164</span>
<span id="165">165</span>
<span id="166">166</span>
<span id="167">167</span>
<span id="168">168</span>
<span id="169">169</span>
<span id="170">170</span>
<span id="171">171</span>
<span id="172">172</span>
<span id="173">173</span>
<span id="174">174</span>
<span id="175">175</span>
<span id="176">176</span>
<span id="177">177</span>
<span id="178">178</span>
<span id="179">179</span>
<span id="180">180</span>
<span id="181">181</span>
<span id="182">182</span>
<span id="183">183</span>
<span id="184">184</span>
<span id="185">185</span>
<span id="186">186</span>
<span id="187">187</span>
<span id="188">188</span>
<span id="189">189</span>
<span id="190">190</span>
<span id="191">191</span>
<span id="192">192</span>
<span id="193">193</span>
<span id="194">194</span>
<span id="195">195</span>
<span id="196">196</span>
<span id="197">197</span>
<span id="198">198</span>
<span id="199">199</span>
<span id="200">200</span>
<span id="201">201</span>
<span id="202">202</span>
<span id="203">203</span>
<span id="204">204</span>
<span id="205">205</span>
<span id="206">206</span>
<span id="207">207</span>
<span id="208">208</span>
<span id="209">209</span>
<span id="210">210</span>
<span id="211">211</span>
<span id="212">212</span>
<span id="213">213</span>
<span id="214">214</span>
<span id="215">215</span>
<span id="216">216</span>
<span id="217">217</span>
<span id="218">218</span>
<span id="219">219</span>
<span id="220">220</span>
<span id="221">221</span>
<span id="222">222</span>
<span id="223">223</span>
<span id="224">224</span>
<span id="225">225</span>
<span id="226">226</span>
<span id="227">227</span>
<span id="228">228</span>
<span id="229">229</span>
<span id="230">230</span>
<span id="231">231</span>
<span id="232">232</span>
<span id="233">233</span>
<span id="234">234</span>
<span id="235">235</span>
<span id="236">236</span>
<span id="237">237</span>
<span id="238">238</span>
<span id="239">239</span>
<span id="240">240</span>
<span id="241">241</span>
<span id="242">242</span>
<span id="243">243</span>
<span id="244">244</span>
<span id="245">245</span>
<span id="246">246</span>
<span id="247">247</span>
<span id="248">248</span>
<span id="249">249</span>
<span id="250">250</span>
<span id="251">251</span>
<span id="252">252</span>
<span id="253">253</span>
<span id="254">254</span>
<span id="255">255</span>
<span id="256">256</span>
<span id="257">257</span>
<span id="258">258</span>
<span id="259">259</span>
<span id="260">260</span>
<span id="261">261</span>
<span id="262">262</span>
<span id="263">263</span>
<span id="264">264</span>
<span id="265">265</span>
<span id="266">266</span>
<span id="267">267</span>
<span id="268">268</span>
<span id="269">269</span>
<span id="270">270</span>
<span id="271">271</span>
<span id="272">272</span>
<span id="273">273</span>
<span id="274">274</span>
<span id="275">275</span>
<span id="276">276</span>
<span id="277">277</span>
<span id="278">278</span>
<span id="279">279</span>
<span id="280">280</span>
<span id="281">281</span>
<span id="282">282</span>
<span id="283">283</span>
<span id="284">284</span>
<span id="285">285</span>
<span id="286">286</span>
<span id="287">287</span>
<span id="288">288</span>
<span id="289">289</span>
<span id="290">290</span>
<span id="291">291</span>
<span id="292">292</span>
<span id="293">293</span>
<span id="294">294</span>
<span id="295">295</span>
<span id="296">296</span>
<span id="297">297</span>
<span id="298">298</span>
<span id="299">299</span>
<span id="300">300</span>
<span id="301">301</span>
<span id="302">302</span>
<span id="303">303</span>
<span id="304">304</span>
<span id="305">305</span>
<span id="306">306</span>
<span id="307">307</span>
<span id="308">308</span>
<span id="309">309</span>
<span id="310">310</span>
<span id="311">311</span>
<span id="312">312</span>
<span id="313">313</span>
<span id="314">314</span>
<span id="315">315</span>
<span id="316">316</span>
<span id="317">317</span>
<span id="318">318</span>
<span id="319">319</span>
<span id="320">320</span>
<span id="321">321</span>
<span id="322">322</span>
<span id="323">323</span>
<span id="324">324</span>
<span id="325">325</span>
<span id="326">326</span>
<span id="327">327</span>
<span id="328">328</span>
<span id="329">329</span>
<span id="330">330</span>
<span id="331">331</span>
<span id="332">332</span>
<span id="333">333</span>
<span id="334">334</span>
<span id="335">335</span>
<span id="336">336</span>
<span id="337">337</span>
<span id="338">338</span>
<span id="339">339</span>
<span id="340">340</span>
<span id="341">341</span>
<span id="342">342</span>
<span id="343">343</span>
<span id="344">344</span>
<span id="345">345</span>
<span id="346">346</span>
<span id="347">347</span>
<span id="348">348</span>
<span id="349">349</span>
<span id="350">350</span>
<span id="351">351</span>
<span id="352">352</span>
<span id="353">353</span>
<span id="354">354</span>
<span id="355">355</span>
<span id="356">356</span>
<span id="357">357</span>
<span id="358">358</span>
<span id="359">359</span>
<span id="360">360</span>
<span id="361">361</span>
<span id="362">362</span>
<span id="363">363</span>
<span id="364">364</span>
<span id="365">365</span>
<span id="366">366</span>
<span id="367">367</span>
<span id="368">368</span>
<span id="369">369</span>
<span id="370">370</span>
<span id="371">371</span>
<span id="372">372</span>
<span id="373">373</span>
<span id="374">374</span>
<span id="375">375</span>
<span id="376">376</span>
<span id="377">377</span>
<span id="378">378</span>
<span id="379">379</span>
<span id="380">380</span>
<span id="381">381</span>
<span id="382">382</span>
<span id="383">383</span>
<span id="384">384</span>
<span id="385">385</span>
<span id="386">386</span>
<span id="387">387</span>
<span id="388">388</span>
<span id="389">389</span>
<span id="390">390</span>
<span id="391">391</span>
<span id="392">392</span>
<span id="393">393</span>
<span id="394">394</span>
<span id="395">395</span>
<span id="396">396</span>
<span id="397">397</span>
<span id="398">398</span>
<span id="399">399</span>
<span id="400">400</span>
<span id="401">401</span>
<span id="402">402</span>
<span id="403">403</span>
<span id="404">404</span>
<span id="405">405</span>
<span id="406">406</span>
<span id="407">407</span>
<span id="408">408</span>
<span id="409">409</span>
<span id="410">410</span>
<span id="411">411</span>
<span id="412">412</span>
<span id="413">413</span>
<span id="414">414</span>
<span id="415">415</span>
<span id="416">416</span>
<span id="417">417</span>
<span id="418">418</span>
<span id="419">419</span>
<span id="420">420</span>
<span id="421">421</span>
<span id="422">422</span>
<span id="423">423</span>
<span id="424">424</span>
<span id="425">425</span>
<span id="426">426</span>
<span id="427">427</span>
<span id="428">428</span>
<span id="429">429</span>
<span id="430">430</span>
<span id="431">431</span>
<span id="432">432</span>
<span id="433">433</span>
<span id="434">434</span>
<span id="435">435</span>
<span id="436">436</span>
<span id="437">437</span>
<span id="438">438</span>
<span id="439">439</span>
<span id="440">440</span>
<span id="441">441</span>
<span id="442">442</span>
<span id="443">443</span>
<span id="444">444</span>
<span id="445">445</span>
<span id="446">446</span>
<span id="447">447</span>
<span id="448">448</span>
<span id="449">449</span>
<span id="450">450</span>
<span id="451">451</span>
<span id="452">452</span>
<span id="453">453</span>
<span id="454">454</span>
<span id="455">455</span>
<span id="456">456</span>
<span id="457">457</span>
<span id="458">458</span>
<span id="459">459</span>
<span id="460">460</span>
<span id="461">461</span>
<span id="462">462</span>
<span id="463">463</span>
<span id="464">464</span>
<span id="465">465</span>
<span id="466">466</span>
<span id="467">467</span>
<span id="468">468</span>
<span id="469">469</span>
<span id="470">470</span>
<span id="471">471</span>
<span id="472">472</span>
<span id="473">473</span>
<span id="474">474</span>
<span id="475">475</span>
<span id="476">476</span>
<span id="477">477</span>
<span id="478">478</span>
<span id="479">479</span>
<span id="480">480</span>
<span id="481">481</span>
<span id="482">482</span>
<span id="483">483</span>
<span id="484">484</span>
<span id="485">485</span>
<span id="486">486</span>
<span id="487">487</span>
<span id="488">488</span>
<span id="489">489</span>
<span id="490">490</span>
<span id="491">491</span>
<span id="492">492</span>
<span id="493">493</span>
<span id="494">494</span>
<span id="495">495</span>
<span id="496">496</span>
<span id="497">497</span>
<span id="498">498</span>
<span id="499">499</span>
<span id="500">500</span>
<span id="501">501</span>
<span id="502">502</span>
<span id="503">503</span>
<span id="504">504</span>
<span id="505">505</span>
<span id="506">506</span>
<span id="507">507</span>
<span id="508">508</span>
<span id="509">509</span>
<span id="510">510</span>
<span id="511">511</span>
<span id="512">512</span>
<span id="513">513</span>
<span id="514">514</span>
<span id="515">515</span>
<span id="516">516</span>
<span id="517">517</span>
<span id="518">518</span>
<span id="519">519</span>
<span id="520">520</span>
<span id="521">521</span>
<span id="522">522</span>
<span id="523">523</span>
<span id="524">524</span>
<span id="525">525</span>
<span id="526">526</span>
<span id="527">527</span>
<span id="528">528</span>
<span id="529">529</span>
<span id="530">530</span>
<span id="531">531</span>
<span id="532">532</span>
<span id="533">533</span>
<span id="534">534</span>
<span id="535">535</span>
<span id="536">536</span>
<span id="537">537</span>
<span id="538">538</span>
<span id="539">539</span>
<span id="540">540</span>
<span id="541">541</span>
<span id="542">542</span>
<span id="543">543</span>
<span id="544">544</span>
<span id="545">545</span>
<span id="546">546</span>
<span id="547">547</span>
<span id="548">548</span>
<span id="549">549</span>
<span id="550">550</span>
<span id="551">551</span>
<span id="552">552</span>
<span id="553">553</span>
<span id="554">554</span>
<span id="555">555</span>
<span id="556">556</span>
<span id="557">557</span>
<span id="558">558</span>
<span id="559">559</span>
<span id="560">560</span>
<span id="561">561</span>
<span id="562">562</span>
<span id="563">563</span>
<span id="564">564</span>
<span id="565">565</span>
<span id="566">566</span>
<span id="567">567</span>
<span id="568">568</span>
<span id="569">569</span>
<span id="570">570</span>
<span id="571">571</span>
<span id="572">572</span>
<span id="573">573</span>
<span id="574">574</span>
<span id="575">575</span>
<span id="576">576</span>
<span id="577">577</span>
<span id="578">578</span>
<span id="579">579</span>
<span id="580">580</span>
<span id="581">581</span>
<span id="582">582</span>
<span id="583">583</span>
<span id="584">584</span>
<span id="585">585</span>
<span id="586">586</span>
<span id="587">587</span>
<span id="588">588</span>
<span id="589">589</span>
<span id="590">590</span>
<span id="591">591</span>
<span id="592">592</span>
<span id="593">593</span>
<span id="594">594</span>
<span id="595">595</span>
<span id="596">596</span>
<span id="597">597</span>
<span id="598">598</span>
<span id="599">599</span>
<span id="600">600</span>
<span id="601">601</span>
<span id="602">602</span>
<span id="603">603</span>
<span id="604">604</span>
<span id="605">605</span>
<span id="606">606</span>
<span id="607">607</span>
<span id="608">608</span>
<span id="609">609</span>
<span id="610">610</span>
<span id="611">611</span>
<span id="612">612</span>
<span id="613">613</span>
<span id="614">614</span>
<span id="615">615</span>
<span id="616">616</span>
<span id="617">617</span>
<span id="618">618</span>
<span id="619">619</span>
<span id="620">620</span>
<span id="621">621</span>
<span id="622">622</span>
<span id="623">623</span>
<span id="624">624</span>
<span id="625">625</span>
<span id="626">626</span>
<span id="627">627</span>
<span id="628">628</span>
<span id="629">629</span>
<span id="630">630</span>
<span id="631">631</span>
<span id="632">632</span>
<span id="633">633</span>
<span id="634">634</span>
<span id="635">635</span>
<span id="636">636</span>
<span id="637">637</span>
<span id="638">638</span>
<span id="639">639</span>
<span id="640">640</span>
<span id="641">641</span>
<span id="642">642</span>
<span id="643">643</span>
<span id="644">644</span>
<span id="645">645</span>
<span id="646">646</span>
<span id="647">647</span>
<span id="648">648</span>
<span id="649">649</span>
<span id="650">650</span>
<span id="651">651</span>
<span id="652">652</span>
<span id="653">653</span>
<span id="654">654</span>
<span id="655">655</span>
<span id="656">656</span>
<span id="657">657</span>
<span id="658">658</span>
<span id="659">659</span>
<span id="660">660</span>
<span id="661">661</span>
<span id="662">662</span>
<span id="663">663</span>
<span id="664">664</span>
<span id="665">665</span>
<span id="666">666</span>
<span id="667">667</span>
<span id="668">668</span>
<span id="669">669</span>
<span id="670">670</span>
<span id="671">671</span>
<span id="672">672</span>
<span id="673">673</span>
<span id="674">674</span>
<span id="675">675</span>
<span id="676">676</span>
<span id="677">677</span>
<span id="678">678</span>
<span id="679">679</span>
<span id="680">680</span>
<span id="681">681</span>
<span id="682">682</span>
<span id="683">683</span>
<span id="684">684</span>
<span id="685">685</span>
<span id="686">686</span>
<span id="687">687</span>
<span id="688">688</span>
<span id="689">689</span>
<span id="690">690</span>
<span id="691">691</span>
<span id="692">692</span>
<span id="693">693</span>
<span id="694">694</span>
<span id="695">695</span>
<span id="696">696</span>
<span id="697">697</span>
<span id="698">698</span>
<span id="699">699</span>
<span id="700">700</span>
<span id="701">701</span>
<span id="702">702</span>
<span id="703">703</span>
<span id="704">704</span>
<span id="705">705</span>
<span id="706">706</span>
<span id="707">707</span>
<span id="708">708</span>
<span id="709">709</span>
<span id="710">710</span>
<span id="711">711</span>
<span id="712">712</span>
<span id="713">713</span>
<span id="714">714</span>
<span id="715">715</span>
<span id="716">716</span>
<span id="717">717</span>
<span id="718">718</span>
<span id="719">719</span>
<span id="720">720</span>
<span id="721">721</span>
<span id="722">722</span>
<span id="723">723</span>
<span id="724">724</span>
<span id="725">725</span>
<span id="726">726</span>
<span id="727">727</span>
<span id="728">728</span>
<span id="729">729</span>
<span id="730">730</span>
<span id="731">731</span>
<span id="732">732</span>
<span id="733">733</span>
<span id="734">734</span>
<span id="735">735</span>
<span id="736">736</span>
<span id="737">737</span>
<span id="738">738</span>
<span id="739">739</span>
<span id="740">740</span>
<span id="741">741</span>
<span id="742">742</span>
<span id="743">743</span>
<span id="744">744</span>
<span id="745">745</span>
<span id="746">746</span>
<span id="747">747</span>
<span id="748">748</span>
<span id="749">749</span>
<span id="750">750</span>
<span id="751">751</span>
<span id="752">752</span>
<span id="753">753</span>
<span id="754">754</span>
<span id="755">755</span>
<span id="756">756</span>
<span id="757">757</span>
<span id="758">758</span>
<span id="759">759</span>
<span id="760">760</span>
<span id="761">761</span>
<span id="762">762</span>
<span id="763">763</span>
<span id="764">764</span>
<span id="765">765</span>
<span id="766">766</span>
<span id="767">767</span>
<span id="768">768</span>
<span id="769">769</span>
<span id="770">770</span>
<span id="771">771</span>
<span id="772">772</span>
<span id="773">773</span>
<span id="774">774</span>
<span id="775">775</span>
<span id="776">776</span>
<span id="777">777</span>
<span id="778">778</span>
<span id="779">779</span>
<span id="780">780</span>
<span id="781">781</span>
<span id="782">782</span>
<span id="783">783</span>
<span id="784">784</span>
<span id="785">785</span>
<span id="786">786</span>
<span id="787">787</span>
<span id="788">788</span>
<span id="789">789</span>
<span id="790">790</span>
<span id="791">791</span>
<span id="792">792</span>
<span id="793">793</span>
<span id="794">794</span>
<span id="795">795</span>
<span id="796">796</span>
<span id="797">797</span>
<span id="798">798</span>
<span id="799">799</span>
<span id="800">800</span>
<span id="801">801</span>
<span id="802">802</span>
<span id="803">803</span>
<span id="804">804</span>
<span id="805">805</span>
<span id="806">806</span>
<span id="807">807</span>
<span id="808">808</span>
<span id="809">809</span>
<span id="810">810</span>
<span id="811">811</span>
<span id="812">812</span>
<span id="813">813</span>
<span id="814">814</span>
<span id="815">815</span>
<span id="816">816</span>
<span id="817">817</span>
<span id="818">818</span>
<span id="819">819</span>
<span id="820">820</span>
<span id="821">821</span>
<span id="822">822</span>
<span id="823">823</span>
<span id="824">824</span>
<span id="825">825</span>
<span id="826">826</span>
<span id="827">827</span>
<span id="828">828</span>
<span id="829">829</span>
<span id="830">830</span>
<span id="831">831</span>
<span id="832">832</span>
<span id="833">833</span>
<span id="834">834</span>
<span id="835">835</span>
<span id="836">836</span>
<span id="837">837</span>
<span id="838">838</span>
<span id="839">839</span>
<span id="840">840</span>
<span id="841">841</span>
<span id="842">842</span>
<span id="843">843</span>
<span id="844">844</span>
<span id="845">845</span>
<span id="846">846</span>
<span id="847">847</span>
<span id="848">848</span>
<span id="849">849</span>
<span id="850">850</span>
<span id="851">851</span>
<span id="852">852</span>
<span id="853">853</span>
<span id="854">854</span>
<span id="855">855</span>
<span id="856">856</span>
<span id="857">857</span>
<span id="858">858</span>
<span id="859">859</span>
<span id="860">860</span>
<span id="861">861</span>
<span id="862">862</span>
<span id="863">863</span>
<span id="864">864</span>
<span id="865">865</span>
<span id="866">866</span>
<span id="867">867</span>
<span id="868">868</span>
<span id="869">869</span>
<span id="870">870</span>
<span id="871">871</span>
<span id="872">872</span>
<span id="873">873</span>
<span id="874">874</span>
<span id="875">875</span>
<span id="876">876</span>
<span id="877">877</span>
<span id="878">878</span>
<span id="879">879</span>
<span id="880">880</span>
<span id="881">881</span>
<span id="882">882</span>
<span id="883">883</span>
<span id="884">884</span>
<span id="885">885</span>
<span id="886">886</span>
<span id="887">887</span>
<span id="888">888</span>
<span id="889">889</span>
<span id="890">890</span>
<span id="891">891</span>
<span id="892">892</span>
<span id="893">893</span>
<span id="894">894</span>
<span id="895">895</span>
<span id="896">896</span>
<span id="897">897</span>
<span id="898">898</span>
<span id="899">899</span>
<span id="900">900</span>
<span id="901">901</span>
<span id="902">902</span>
<span id="903">903</span>
<span id="904">904</span>
<span id="905">905</span>
<span id="906">906</span>
<span id="907">907</span>
<span id="908">908</span>
<span id="909">909</span>
<span id="910">910</span>
<span id="911">911</span>
<span id="912">912</span>
<span id="913">913</span>
<span id="914">914</span>
<span id="915">915</span>
<span id="916">916</span>
<span id="917">917</span>
<span id="918">918</span>
<span id="919">919</span>
<span id="920">920</span>
<span id="921">921</span>
<span id="922">922</span>
<span id="923">923</span>
<span id="924">924</span>
<span id="925">925</span>
<span id="926">926</span>
<span id="927">927</span>
<span id="928">928</span>
<span id="929">929</span>
<span id="930">930</span>
<span id="931">931</span>
<span id="932">932</span>
<span id="933">933</span>
<span id="934">934</span>
<span id="935">935</span>
<span id="936">936</span>
<span id="937">937</span>
<span id="938">938</span>
<span id="939">939</span>
<span id="940">940</span>
<span id="941">941</span>
<span id="942">942</span>
<span id="943">943</span>
<span id="944">944</span>
<span id="945">945</span>
<span id="946">946</span>
<span id="947">947</span>
<span id="948">948</span>
<span id="949">949</span>
<span id="950">950</span>
<span id="951">951</span>
<span id="952">952</span>
<span id="953">953</span>
<span id="954">954</span>
<span id="955">955</span>
<span id="956">956</span>
<span id="957">957</span>
<span id="958">958</span>
<span id="959">959</span>
<span id="960">960</span>
<span id="961">961</span>
<span id="962">962</span>
<span id="963">963</span>
<span id="964">964</span>
<span id="965">965</span>
<span id="966">966</span>
<span id="967">967</span>
<span id="968">968</span>
<span id="969">969</span>
<span id="970">970</span>
<span id="971">971</span>
<span id="972">972</span>
<span id="973">973</span>
<span id="974">974</span>
<span id="975">975</span>
<span id="976">976</span>
<span id="977">977</span>
<span id="978">978</span>
<span id="979">979</span>
<span id="980">980</span>
<span id="981">981</span>
<span id="982">982</span>
<span id="983">983</span>
<span id="984">984</span>
<span id="985">985</span>
<span id="986">986</span>
<span id="987">987</span>
<span id="988">988</span>
<span id="989">989</span>
<span id="990">990</span>
<span id="991">991</span>
<span id="992">992</span>
<span id="993">993</span>
<span id="994">994</span>
<span id="995">995</span>
<span id="996">996</span>
<span id="997">997</span>
<span id="998">998</span>
<span id="999">999</span>
<span id="1000">1000</span>
<span id="1001">1001</span>
<span id="1002">1002</span>
<span id="1003">1003</span>
<span id="1004">1004</span>
<span id="1005">1005</span>
<span id="1006">1006</span>
<span id="1007">1007</span>
<span id="1008">1008</span>
<span id="1009">1009</span>
<span id="1010">1010</span>
<span id="1011">1011</span>
<span id="1012">1012</span>
<span id="1013">1013</span>
<span id="1014">1014</span>
<span id="1015">1015</span>
<span id="1016">1016</span>
<span id="1017">1017</span>
<span id="1018">1018</span>
<span id="1019">1019</span>
<span id="1020">1020</span>
<span id="1021">1021</span>
<span id="1022">1022</span>
<span id="1023">1023</span>
<span id="1024">1024</span>
<span id="1025">1025</span>
<span id="1026">1026</span>
<span id="1027">1027</span>
<span id="1028">1028</span>
<span id="1029">1029</span>
<span id="1030">1030</span>
<span id="1031">1031</span>
<span id="1032">1032</span>
<span id="1033">1033</span>
<span id="1034">1034</span>
<span id="1035">1035</span>
<span id="1036">1036</span>
<span id="1037">1037</span>
<span id="1038">1038</span>
<span id="1039">1039</span>
<span id="1040">1040</span>
<span id="1041">1041</span>
<span id="1042">1042</span>
<span id="1043">1043</span>
<span id="1044">1044</span>
<span id="1045">1045</span>
<span id="1046">1046</span>
<span id="1047">1047</span>
<span id="1048">1048</span>
<span id="1049">1049</span>
<span id="1050">1050</span>
<span id="1051">1051</span>
<span id="1052">1052</span>
<span id="1053">1053</span>
<span id="1054">1054</span>
<span id="1055">1055</span>
<span id="1056">1056</span>
<span id="1057">1057</span>
<span id="1058">1058</span>
<span id="1059">1059</span>
<span id="1060">1060</span>
<span id="1061">1061</span>
<span id="1062">1062</span>
<span id="1063">1063</span>
<span id="1064">1064</span>
<span id="1065">1065</span>
<span id="1066">1066</span>
<span id="1067">1067</span>
<span id="1068">1068</span>
<span id="1069">1069</span>
<span id="1070">1070</span>
<span id="1071">1071</span>
<span id="1072">1072</span>
<span id="1073">1073</span>
<span id="1074">1074</span>
<span id="1075">1075</span>
<span id="1076">1076</span>
<span id="1077">1077</span>
<span id="1078">1078</span>
<span id="1079">1079</span>
<span id="1080">1080</span>
<span id="1081">1081</span>
<span id="1082">1082</span>
<span id="1083">1083</span>
<span id="1084">1084</span>
<span id="1085">1085</span>
<span id="1086">1086</span>
<span id="1087">1087</span>
<span id="1088">1088</span>
<span id="1089">1089</span>
<span id="1090">1090</span>
<span id="1091">1091</span>
<span id="1092">1092</span>
<span id="1093">1093</span>
<span id="1094">1094</span>
<span id="1095">1095</span>
<span id="1096">1096</span>
<span id="1097">1097</span>
<span id="1098">1098</span>
<span id="1099">1099</span>
<span id="1100">1100</span>
<span id="1101">1101</span>
<span id="1102">1102</span>
<span id="1103">1103</span>
<span id="1104">1104</span>
<span id="1105">1105</span>
<span id="1106">1106</span>
<span id="1107">1107</span>
<span id="1108">1108</span>
<span id="1109">1109</span>
<span id="1110">1110</span>
<span id="1111">1111</span>
<span id="1112">1112</span>
<span id="1113">1113</span>
<span id="1114">1114</span>
<span id="1115">1115</span>
<span id="1116">1116</span>
<span id="1117">1117</span>
<span id="1118">1118</span>
<span id="1119">1119</span>
<span id="1120">1120</span>
<span id="1121">1121</span>
<span id="1122">1122</span>
<span id="1123">1123</span>
<span id="1124">1124</span>
<span id="1125">1125</span>
<span id="1126">1126</span>
<span id="1127">1127</span>
<span id="1128">1128</span>
<span id="1129">1129</span>
<span id="1130">1130</span>
<span id="1131">1131</span>
<span id="1132">1132</span>
<span id="1133">1133</span>
<span id="1134">1134</span>
<span id="1135">1135</span>
<span id="1136">1136</span>
<span id="1137">1137</span>
<span id="1138">1138</span>
<span id="1139">1139</span>
<span id="1140">1140</span>
<span id="1141">1141</span>
<span id="1142">1142</span>
<span id="1143">1143</span>
<span id="1144">1144</span>
<span id="1145">1145</span>
<span id="1146">1146</span>
<span id="1147">1147</span>
<span id="1148">1148</span>
<span id="1149">1149</span>
<span id="1150">1150</span>
<span id="1151">1151</span>
<span id="1152">1152</span>
<span id="1153">1153</span>
<span id="1154">1154</span>
<span id="1155">1155</span>
<span id="1156">1156</span>
<span id="1157">1157</span>
<span id="1158">1158</span>
<span id="1159">1159</span>
<span id="1160">1160</span>
<span id="1161">1161</span>
<span id="1162">1162</span>
<span id="1163">1163</span>
<span id="1164">1164</span>
<span id="1165">1165</span>
<span id="1166">1166</span>
<span id="1167">1167</span>
<span id="1168">1168</span>
<span id="1169">1169</span>
<span id="1170">1170</span>
<span id="1171">1171</span>
<span id="1172">1172</span>
<span id="1173">1173</span>
<span id="1174">1174</span>
<span id="1175">1175</span>
<span id="1176">1176</span>
<span id="1177">1177</span>
<span id="1178">1178</span>
<span id="1179">1179</span>
<span id="1180">1180</span>
<span id="1181">1181</span>
<span id="1182">1182</span>
<span id="1183">1183</span>
<span id="1184">1184</span>
<span id="1185">1185</span>
<span id="1186">1186</span>
<span id="1187">1187</span>
<span id="1188">1188</span>
<span id="1189">1189</span>
<span id="1190">1190</span>
<span id="1191">1191</span>
<span id="1192">1192</span>
<span id="1193">1193</span>
<span id="1194">1194</span>
<span id="1195">1195</span>
<span id="1196">1196</span>
<span id="1197">1197</span>
<span id="1198">1198</span>
<span id="1199">1199</span>
<span id="1200">1200</span>
<span id="1201">1201</span>
<span id="1202">1202</span>
<span id="1203">1203</span>
<span id="1204">1204</span>
<span id="1205">1205</span>
<span id="1206">1206</span>
<span id="1207">1207</span>
<span id="1208">1208</span>
<span id="1209">1209</span>
<span id="1210">1210</span>
<span id="1211">1211</span>
<span id="1212">1212</span>
<span id="1213">1213</span>
<span id="1214">1214</span>
<span id="1215">1215</span>
<span id="1216">1216</span>
<span id="1217">1217</span>
<span id="1218">1218</span>
<span id="1219">1219</span>
<span id="1220">1220</span>
<span id="1221">1221</span>
<span id="1222">1222</span>
<span id="1223">1223</span>
<span id="1224">1224</span>
<span id="1225">1225</span>
<span id="1226">1226</span>
<span id="1227">1227</span>
<span id="1228">1228</span>
<span id="1229">1229</span>
<span id="1230">1230</span>
<span id="1231">1231</span>
<span id="1232">1232</span>
<span id="1233">1233</span>
<span id="1234">1234</span>
<span id="1235">1235</span>
<span id="1236">1236</span>
<span id="1237">1237</span>
<span id="1238">1238</span>
<span id="1239">1239</span>
<span id="1240">1240</span>
<span id="1241">1241</span>
<span id="1242">1242</span>
<span id="1243">1243</span>
<span id="1244">1244</span>
<span id="1245">1245</span>
<span id="1246">1246</span>
<span id="1247">1247</span>
<span id="1248">1248</span>
<span id="1249">1249</span>
<span id="1250">1250</span>
<span id="1251">1251</span>
<span id="1252">1252</span>
<span id="1253">1253</span>
<span id="1254">1254</span>
<span id="1255">1255</span>
<span id="1256">1256</span>
<span id="1257">1257</span>
<span id="1258">1258</span>
<span id="1259">1259</span>
<span id="1260">1260</span>
<span id="1261">1261</span>
<span id="1262">1262</span>
<span id="1263">1263</span>
<span id="1264">1264</span>
<span id="1265">1265</span>
<span id="1266">1266</span>
<span id="1267">1267</span>
<span id="1268">1268</span>
<span id="1269">1269</span>
<span id="1270">1270</span>
<span id="1271">1271</span>
<span id="1272">1272</span>
<span id="1273">1273</span>
<span id="1274">1274</span>
<span id="1275">1275</span>
<span id="1276">1276</span>
<span id="1277">1277</span>
<span id="1278">1278</span>
<span id="1279">1279</span>
<span id="1280">1280</span>
<span id="1281">1281</span>
<span id="1282">1282</span>
<span id="1283">1283</span>
<span id="1284">1284</span>
<span id="1285">1285</span>
<span id="1286">1286</span>
<span id="1287">1287</span>
<span id="1288">1288</span>
<span id="1289">1289</span>
<span id="1290">1290</span>
<span id="1291">1291</span>
<span id="1292">1292</span>
<span id="1293">1293</span>
<span id="1294">1294</span>
<span id="1295">1295</span>
<span id="1296">1296</span>
<span id="1297">1297</span>
<span id="1298">1298</span>
<span id="1299">1299</span>
<span id="1300">1300</span>
<span id="1301">1301</span>
<span id="1302">1302</span>
<span id="1303">1303</span>
<span id="1304">1304</span>
<span id="1305">1305</span>
<span id="1306">1306</span>
<span id="1307">1307</span>
<span id="1308">1308</span>
<span id="1309">1309</span>
<span id="1310">1310</span>
<span id="1311">1311</span>
<span id="1312">1312</span>
<span id="1313">1313</span>
<span id="1314">1314</span>
<span id="1315">1315</span>
<span id="1316">1316</span>
<span id="1317">1317</span>
<span id="1318">1318</span>
<span id="1319">1319</span>
<span id="1320">1320</span>
<span id="1321">1321</span>
<span id="1322">1322</span>
<span id="1323">1323</span>
<span id="1324">1324</span>
<span id="1325">1325</span>
<span id="1326">1326</span>
<span id="1327">1327</span>
<span id="1328">1328</span>
<span id="1329">1329</span>
<span id="1330">1330</span>
<span id="1331">1331</span>
<span id="1332">1332</span>
<span id="1333">1333</span>
<span id="1334">1334</span>
<span id="1335">1335</span>
<span id="1336">1336</span>
<span id="1337">1337</span>
<span id="1338">1338</span>
<span id="1339">1339</span>
<span id="1340">1340</span>
<span id="1341">1341</span>
<span id="1342">1342</span>
<span id="1343">1343</span>
<span id="1344">1344</span>
<span id="1345">1345</span>
<span id="1346">1346</span>
<span id="1347">1347</span>
<span id="1348">1348</span>
<span id="1349">1349</span>
<span id="1350">1350</span>
<span id="1351">1351</span>
<span id="1352">1352</span>
<span id="1353">1353</span>
<span id="1354">1354</span>
<span id="1355">1355</span>
<span id="1356">1356</span>
<span id="1357">1357</span>
<span id="1358">1358</span>
<span id="1359">1359</span>
<span id="1360">1360</span>
<span id="1361">1361</span>
<span id="1362">1362</span>
<span id="1363">1363</span>
<span id="1364">1364</span>
<span id="1365">1365</span>
<span id="1366">1366</span>
<span id="1367">1367</span>
<span id="1368">1368</span>
<span id="1369">1369</span>
<span id="1370">1370</span>
<span id="1371">1371</span>
<span id="1372">1372</span>
<span id="1373">1373</span>
<span id="1374">1374</span>
<span id="1375">1375</span>
<span id="1376">1376</span>
<span id="1377">1377</span>
<span id="1378">1378</span>
<span id="1379">1379</span>
<span id="1380">1380</span>
<span id="1381">1381</span>
<span id="1382">1382</span>
<span id="1383">1383</span>
<span id="1384">1384</span>
</pre><pre class="rust"><code><span class="comment">// * This file is part of the uutils coreutils package.</span>
<span class="comment">// *</span>
<span class="comment">// * (c) Akira Hayakawa &lt;ruby.wktk@gmail.com&gt;</span>
<span class="comment">// *</span>
<span class="comment">// * For the full copyright and license information, please view the LICENSE</span>
<span class="comment">// * file that was distributed with this source code.</span>
<span class="comment">// spell-checker:ignore (ToDO) PREFIXaa PREFIXab nbbbb ncccc</span>
<span class="kw">mod</span> <span class="ident">filenames</span>;
<span class="kw">mod</span> <span class="ident">number</span>;
<span class="kw">mod</span> <span class="ident">platform</span>;
<span class="kw">use</span> <span class="ident"><span class="kw">crate</span>::filenames::FilenameIterator</span>;
<span class="kw">use</span> <span class="ident"><span class="kw">crate</span>::filenames::SuffixType</span>;
<span class="kw">use</span> <span class="ident">clap</span>::{<span class="ident">crate_version</span>, <span class="ident">Arg</span>, <span class="ident">ArgMatches</span>, <span class="ident">Command</span>, <span class="ident">ValueSource</span>};
<span class="kw">use</span> <span class="ident">std::env</span>;
<span class="kw">use</span> <span class="ident">std::fmt</span>;
<span class="kw">use</span> <span class="ident">std::fs</span>::{<span class="ident">metadata</span>, <span class="ident">File</span>};
<span class="kw">use</span> <span class="ident">std::io</span>;
<span class="kw">use</span> <span class="ident">std::io</span>::{<span class="ident">stdin</span>, <span class="ident">BufRead</span>, <span class="ident">BufReader</span>, <span class="ident">BufWriter</span>, <span class="ident">ErrorKind</span>, <span class="ident">Read</span>, <span class="ident">Write</span>};
<span class="kw">use</span> <span class="ident">std::path::Path</span>;
<span class="kw">use</span> <span class="ident">uucore::display::Quotable</span>;
<span class="kw">use</span> <span class="ident">uucore::error</span>::{<span class="ident">FromIo</span>, <span class="ident">UIoError</span>, <span class="ident">UResult</span>, <span class="ident">USimpleError</span>, <span class="ident">UUsageError</span>};
<span class="kw">use</span> <span class="ident">uucore::format_usage</span>;
<span class="kw">use</span> <span class="ident">uucore::parse_size</span>::{<span class="ident">parse_size</span>, <span class="ident">ParseSizeError</span>};
<span class="kw">use</span> <span class="ident">uucore::uio_error</span>;
<span class="kw">static</span> <span class="ident">OPT_BYTES</span>: <span class="kw-2">&amp;</span><span class="ident">str</span> <span class="op">=</span> <span class="string">&quot;bytes&quot;</span>;
<span class="kw">static</span> <span class="ident">OPT_LINE_BYTES</span>: <span class="kw-2">&amp;</span><span class="ident">str</span> <span class="op">=</span> <span class="string">&quot;line-bytes&quot;</span>;
<span class="kw">static</span> <span class="ident">OPT_LINES</span>: <span class="kw-2">&amp;</span><span class="ident">str</span> <span class="op">=</span> <span class="string">&quot;lines&quot;</span>;
<span class="kw">static</span> <span class="ident">OPT_ADDITIONAL_SUFFIX</span>: <span class="kw-2">&amp;</span><span class="ident">str</span> <span class="op">=</span> <span class="string">&quot;additional-suffix&quot;</span>;
<span class="kw">static</span> <span class="ident">OPT_FILTER</span>: <span class="kw-2">&amp;</span><span class="ident">str</span> <span class="op">=</span> <span class="string">&quot;filter&quot;</span>;
<span class="kw">static</span> <span class="ident">OPT_NUMBER</span>: <span class="kw-2">&amp;</span><span class="ident">str</span> <span class="op">=</span> <span class="string">&quot;number&quot;</span>;
<span class="kw">static</span> <span class="ident">OPT_NUMERIC_SUFFIXES</span>: <span class="kw-2">&amp;</span><span class="ident">str</span> <span class="op">=</span> <span class="string">&quot;numeric-suffixes&quot;</span>;
<span class="kw">static</span> <span class="ident">OPT_HEX_SUFFIXES</span>: <span class="kw-2">&amp;</span><span class="ident">str</span> <span class="op">=</span> <span class="string">&quot;hex-suffixes&quot;</span>;
<span class="kw">static</span> <span class="ident">OPT_SUFFIX_LENGTH</span>: <span class="kw-2">&amp;</span><span class="ident">str</span> <span class="op">=</span> <span class="string">&quot;suffix-length&quot;</span>;
<span class="kw">static</span> <span class="ident">OPT_DEFAULT_SUFFIX_LENGTH</span>: <span class="kw-2">&amp;</span><span class="ident">str</span> <span class="op">=</span> <span class="string">&quot;0&quot;</span>;
<span class="kw">static</span> <span class="ident">OPT_VERBOSE</span>: <span class="kw-2">&amp;</span><span class="ident">str</span> <span class="op">=</span> <span class="string">&quot;verbose&quot;</span>;
<span class="comment">//The ---io-blksize parameter is consumed and ignored.</span>
<span class="comment">//The parameter is included to make GNU coreutils tests pass.</span>
<span class="kw">static</span> <span class="ident">OPT_IO_BLKSIZE</span>: <span class="kw-2">&amp;</span><span class="ident">str</span> <span class="op">=</span> <span class="string">&quot;-io-blksize&quot;</span>;
<span class="kw">static</span> <span class="ident">OPT_ELIDE_EMPTY_FILES</span>: <span class="kw-2">&amp;</span><span class="ident">str</span> <span class="op">=</span> <span class="string">&quot;elide-empty-files&quot;</span>;
<span class="kw">static</span> <span class="ident">ARG_INPUT</span>: <span class="kw-2">&amp;</span><span class="ident">str</span> <span class="op">=</span> <span class="string">&quot;input&quot;</span>;
<span class="kw">static</span> <span class="ident">ARG_PREFIX</span>: <span class="kw-2">&amp;</span><span class="ident">str</span> <span class="op">=</span> <span class="string">&quot;prefix&quot;</span>;
<span class="kw">const</span> <span class="ident">USAGE</span>: <span class="kw-2">&amp;</span><span class="ident">str</span> <span class="op">=</span> <span class="string">&quot;{} [OPTION]... [INPUT [PREFIX]]&quot;</span>;
<span class="kw">const</span> <span class="ident">AFTER_HELP</span>: <span class="kw-2">&amp;</span><span class="ident">str</span> <span class="op">=</span> <span class="string">&quot;\
Output fixed-size pieces of INPUT to PREFIXaa, PREFIXab, ...; default \
size is 1000, and default PREFIX is &#39;x&#39;. With no INPUT, or when INPUT is \
-, read standard input.&quot;</span>;
<span class="attribute">#[<span class="ident">uucore::main</span>]</span>
<span class="kw">pub</span> <span class="kw">fn</span> <span class="ident">uumain</span>(<span class="ident">args</span>: <span class="kw">impl</span> <span class="ident">uucore::Args</span>) -&gt; <span class="ident">UResult</span><span class="op">&lt;</span>()<span class="op">&gt;</span> {
<span class="kw">let</span> <span class="ident">matches</span> <span class="op">=</span> <span class="ident">uu_app</span>().<span class="ident">try_get_matches_from</span>(<span class="ident">args</span>)<span class="question-mark">?</span>;
<span class="kw">match</span> <span class="ident">Settings::from</span>(<span class="kw-2">&amp;</span><span class="ident">matches</span>) {
<span class="prelude-val">Ok</span>(<span class="ident">settings</span>) =&gt; <span class="ident">split</span>(<span class="kw-2">&amp;</span><span class="ident">settings</span>),
<span class="prelude-val">Err</span>(<span class="ident">e</span>) <span class="kw">if</span> <span class="ident">e</span>.<span class="ident">requires_usage</span>() =&gt; <span class="prelude-val">Err</span>(<span class="ident">UUsageError::new</span>(<span class="number">1</span>, <span class="macro">format!</span>(<span class="string">&quot;{}&quot;</span>, <span class="ident">e</span>))),
<span class="prelude-val">Err</span>(<span class="ident">e</span>) =&gt; <span class="prelude-val">Err</span>(<span class="ident">USimpleError::new</span>(<span class="number">1</span>, <span class="macro">format!</span>(<span class="string">&quot;{}&quot;</span>, <span class="ident">e</span>))),
}
}
<span class="kw">pub</span> <span class="kw">fn</span> <span class="ident">uu_app</span><span class="op">&lt;</span><span class="lifetime">&#39;a</span><span class="op">&gt;</span>() -&gt; <span class="ident">Command</span><span class="op">&lt;</span><span class="lifetime">&#39;a</span><span class="op">&gt;</span> {
<span class="ident">Command::new</span>(<span class="ident">uucore::util_name</span>())
.<span class="ident">version</span>(<span class="macro">crate_version!</span>())
.<span class="ident">about</span>(<span class="string">&quot;Create output files containing consecutive or interleaved sections of input&quot;</span>)
.<span class="ident">after_help</span>(<span class="ident">AFTER_HELP</span>)
.<span class="ident">override_usage</span>(<span class="ident">format_usage</span>(<span class="ident">USAGE</span>))
.<span class="ident">infer_long_args</span>(<span class="bool-val">true</span>)
<span class="comment">// strategy (mutually exclusive)</span>
.<span class="ident">arg</span>(
<span class="ident">Arg::new</span>(<span class="ident">OPT_BYTES</span>)
.<span class="ident">short</span>(<span class="string">&#39;b&#39;</span>)
.<span class="ident">long</span>(<span class="ident">OPT_BYTES</span>)
.<span class="ident">takes_value</span>(<span class="bool-val">true</span>)
.<span class="ident">value_name</span>(<span class="string">&quot;SIZE&quot;</span>)
.<span class="ident">help</span>(<span class="string">&quot;put SIZE bytes per output file&quot;</span>),
)
.<span class="ident">arg</span>(
<span class="ident">Arg::new</span>(<span class="ident">OPT_LINE_BYTES</span>)
.<span class="ident">short</span>(<span class="string">&#39;C&#39;</span>)
.<span class="ident">long</span>(<span class="ident">OPT_LINE_BYTES</span>)
.<span class="ident">takes_value</span>(<span class="bool-val">true</span>)
.<span class="ident">value_name</span>(<span class="string">&quot;SIZE&quot;</span>)
.<span class="ident">default_value</span>(<span class="string">&quot;2&quot;</span>)
.<span class="ident">help</span>(<span class="string">&quot;put at most SIZE bytes of lines per output file&quot;</span>),
)
.<span class="ident">arg</span>(
<span class="ident">Arg::new</span>(<span class="ident">OPT_LINES</span>)
.<span class="ident">short</span>(<span class="string">&#39;l&#39;</span>)
.<span class="ident">long</span>(<span class="ident">OPT_LINES</span>)
.<span class="ident">takes_value</span>(<span class="bool-val">true</span>)
.<span class="ident">value_name</span>(<span class="string">&quot;NUMBER&quot;</span>)
.<span class="ident">default_value</span>(<span class="string">&quot;1000&quot;</span>)
.<span class="ident">help</span>(<span class="string">&quot;put NUMBER lines/records per output file&quot;</span>),
)
.<span class="ident">arg</span>(
<span class="ident">Arg::new</span>(<span class="ident">OPT_NUMBER</span>)
.<span class="ident">short</span>(<span class="string">&#39;n&#39;</span>)
.<span class="ident">long</span>(<span class="ident">OPT_NUMBER</span>)
.<span class="ident">takes_value</span>(<span class="bool-val">true</span>)
.<span class="ident">value_name</span>(<span class="string">&quot;CHUNKS&quot;</span>)
.<span class="ident">help</span>(<span class="string">&quot;generate CHUNKS output files; see explanation below&quot;</span>),
)
<span class="comment">// rest of the arguments</span>
.<span class="ident">arg</span>(
<span class="ident">Arg::new</span>(<span class="ident">OPT_ADDITIONAL_SUFFIX</span>)
.<span class="ident">long</span>(<span class="ident">OPT_ADDITIONAL_SUFFIX</span>)
.<span class="ident">takes_value</span>(<span class="bool-val">true</span>)
.<span class="ident">value_name</span>(<span class="string">&quot;SUFFIX&quot;</span>)
.<span class="ident">default_value</span>(<span class="string">&quot;&quot;</span>)
.<span class="ident">help</span>(<span class="string">&quot;additional SUFFIX to append to output file names&quot;</span>),
)
.<span class="ident">arg</span>(
<span class="ident">Arg::new</span>(<span class="ident">OPT_FILTER</span>)
.<span class="ident">long</span>(<span class="ident">OPT_FILTER</span>)
.<span class="ident">takes_value</span>(<span class="bool-val">true</span>)
.<span class="ident">value_name</span>(<span class="string">&quot;COMMAND&quot;</span>)
.<span class="ident">value_hint</span>(<span class="ident">clap::ValueHint::CommandName</span>)
.<span class="ident">help</span>(
<span class="string">&quot;write to shell COMMAND; file name is $FILE (Currently not implemented for Windows)&quot;</span>,
),
)
.<span class="ident">arg</span>(
<span class="ident">Arg::new</span>(<span class="ident">OPT_ELIDE_EMPTY_FILES</span>)
.<span class="ident">long</span>(<span class="ident">OPT_ELIDE_EMPTY_FILES</span>)
.<span class="ident">short</span>(<span class="string">&#39;e&#39;</span>)
.<span class="ident">takes_value</span>(<span class="bool-val">false</span>)
.<span class="ident">help</span>(<span class="string">&quot;do not generate empty output files with &#39;-n&#39;&quot;</span>),
)
.<span class="ident">arg</span>(
<span class="ident">Arg::new</span>(<span class="ident">OPT_NUMERIC_SUFFIXES</span>)
.<span class="ident">short</span>(<span class="string">&#39;d&#39;</span>)
.<span class="ident">long</span>(<span class="ident">OPT_NUMERIC_SUFFIXES</span>)
.<span class="ident">takes_value</span>(<span class="bool-val">true</span>)
.<span class="ident">default_missing_value</span>(<span class="string">&quot;0&quot;</span>)
.<span class="ident">help</span>(<span class="string">&quot;use numeric suffixes instead of alphabetic&quot;</span>),
)
.<span class="ident">arg</span>(
<span class="ident">Arg::new</span>(<span class="ident">OPT_SUFFIX_LENGTH</span>)
.<span class="ident">short</span>(<span class="string">&#39;a&#39;</span>)
.<span class="ident">long</span>(<span class="ident">OPT_SUFFIX_LENGTH</span>)
.<span class="ident">takes_value</span>(<span class="bool-val">true</span>)
.<span class="ident">value_name</span>(<span class="string">&quot;N&quot;</span>)
.<span class="ident">default_value</span>(<span class="ident">OPT_DEFAULT_SUFFIX_LENGTH</span>)
.<span class="ident">help</span>(<span class="string">&quot;use suffixes of fixed length N. 0 implies dynamic length.&quot;</span>),
)
.<span class="ident">arg</span>(
<span class="ident">Arg::new</span>(<span class="ident">OPT_HEX_SUFFIXES</span>)
.<span class="ident">short</span>(<span class="string">&#39;x&#39;</span>)
.<span class="ident">long</span>(<span class="ident">OPT_HEX_SUFFIXES</span>)
.<span class="ident">takes_value</span>(<span class="bool-val">true</span>)
.<span class="ident">default_missing_value</span>(<span class="string">&quot;0&quot;</span>)
.<span class="ident">help</span>(<span class="string">&quot;use hex suffixes instead of alphabetic&quot;</span>),
)
.<span class="ident">arg</span>(
<span class="ident">Arg::new</span>(<span class="ident">OPT_VERBOSE</span>)
.<span class="ident">long</span>(<span class="ident">OPT_VERBOSE</span>)
.<span class="ident">help</span>(<span class="string">&quot;print a diagnostic just before each output file is opened&quot;</span>),
)
.<span class="ident">arg</span>(
<span class="ident">Arg::new</span>(<span class="ident">OPT_IO_BLKSIZE</span>)
.<span class="ident">long</span>(<span class="ident">OPT_IO_BLKSIZE</span>)
.<span class="ident">alias</span>(<span class="ident">OPT_IO_BLKSIZE</span>)
.<span class="ident">takes_value</span>(<span class="bool-val">true</span>)
.<span class="ident">hide</span>(<span class="bool-val">true</span>),
)
.<span class="ident">arg</span>(
<span class="ident">Arg::new</span>(<span class="ident">ARG_INPUT</span>)
.<span class="ident">takes_value</span>(<span class="bool-val">true</span>)
.<span class="ident">default_value</span>(<span class="string">&quot;-&quot;</span>)
.<span class="ident">index</span>(<span class="number">1</span>)
.<span class="ident">value_hint</span>(<span class="ident">clap::ValueHint::FilePath</span>),
)
.<span class="ident">arg</span>(
<span class="ident">Arg::new</span>(<span class="ident">ARG_PREFIX</span>)
.<span class="ident">takes_value</span>(<span class="bool-val">true</span>)
.<span class="ident">default_value</span>(<span class="string">&quot;x&quot;</span>)
.<span class="ident">index</span>(<span class="number">2</span>),
)
}
<span class="doccomment">/// Sub-strategy to use when splitting a file into a specific number of chunks.</span>
<span class="attribute">#[<span class="ident">derive</span>(<span class="ident">Debug</span>, <span class="ident">PartialEq</span>)]</span>
<span class="kw">enum</span> <span class="ident">NumberType</span> {
<span class="doccomment">/// Split into a specific number of chunks by byte.</span>
<span class="ident">Bytes</span>(<span class="ident">u64</span>),
<span class="doccomment">/// Split into a specific number of chunks by line (approximately).</span>
<span class="ident">Lines</span>(<span class="ident">u64</span>),
<span class="doccomment">/// Split into a specific number of chunks by line</span>
<span class="doccomment">/// (approximately), but output only the *k*th chunk.</span>
<span class="ident">KthLines</span>(<span class="ident">u64</span>, <span class="ident">u64</span>),
<span class="doccomment">/// Assign lines via round-robin to the specified number of output chunks.</span>
<span class="ident">RoundRobin</span>(<span class="ident">u64</span>),
<span class="doccomment">/// Assign lines via round-robin to the specified number of output</span>
<span class="doccomment">/// chunks, but output only the *k*th chunk.</span>
<span class="ident">KthRoundRobin</span>(<span class="ident">u64</span>, <span class="ident">u64</span>),
}
<span class="kw">impl</span> <span class="ident">NumberType</span> {
<span class="doccomment">/// The number of chunks for this number type.</span>
<span class="kw">fn</span> <span class="ident">num_chunks</span>(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; <span class="ident">u64</span> {
<span class="kw">match</span> <span class="self">self</span> {
<span class="ident"><span class="self">Self</span>::Bytes</span>(<span class="ident">n</span>) =&gt; <span class="kw-2">*</span><span class="ident">n</span>,
<span class="ident"><span class="self">Self</span>::Lines</span>(<span class="ident">n</span>) =&gt; <span class="kw-2">*</span><span class="ident">n</span>,
<span class="ident"><span class="self">Self</span>::KthLines</span>(<span class="kw">_</span>, <span class="ident">n</span>) =&gt; <span class="kw-2">*</span><span class="ident">n</span>,
<span class="ident"><span class="self">Self</span>::RoundRobin</span>(<span class="ident">n</span>) =&gt; <span class="kw-2">*</span><span class="ident">n</span>,
<span class="ident"><span class="self">Self</span>::KthRoundRobin</span>(<span class="kw">_</span>, <span class="ident">n</span>) =&gt; <span class="kw-2">*</span><span class="ident">n</span>,
}
}
}
<span class="doccomment">/// An error due to an invalid parameter to the `-n` command-line option.</span>
<span class="attribute">#[<span class="ident">derive</span>(<span class="ident">Debug</span>, <span class="ident">PartialEq</span>)]</span>
<span class="kw">enum</span> <span class="ident">NumberTypeError</span> {
<span class="doccomment">/// The number of chunks was invalid.</span>
<span class="doccomment">///</span>
<span class="doccomment">/// This can happen if the value of `N` in any of the following</span>
<span class="doccomment">/// command-line options is not a positive integer:</span>
<span class="doccomment">///</span>
<span class="doccomment">/// ```ignore</span>
<span class="doccomment">/// -n N</span>
<span class="doccomment">/// -n l/N</span>
<span class="doccomment">/// -n l/K/N</span>
<span class="doccomment">/// -n r/N</span>
<span class="doccomment">/// -n r/K/N</span>
<span class="doccomment">/// ```</span>
<span class="ident">NumberOfChunks</span>(<span class="ident">String</span>),
<span class="doccomment">/// The chunk number was invalid.</span>
<span class="doccomment">///</span>
<span class="doccomment">/// This can happen if the value of `K` in any of the following</span>
<span class="doccomment">/// command-line options is not a positive integer:</span>
<span class="doccomment">///</span>
<span class="doccomment">/// ```ignore</span>
<span class="doccomment">/// -n l/K/N</span>
<span class="doccomment">/// -n r/K/N</span>
<span class="doccomment">/// ```</span>
<span class="ident">ChunkNumber</span>(<span class="ident">String</span>),
}
<span class="kw">impl</span> <span class="ident">NumberType</span> {
<span class="doccomment">/// Parse a `NumberType` from a string.</span>
<span class="doccomment">///</span>
<span class="doccomment">/// The following strings are valid arguments:</span>
<span class="doccomment">///</span>
<span class="doccomment">/// ```ignore</span>
<span class="doccomment">/// &quot;N&quot;</span>
<span class="doccomment">/// &quot;l/N&quot;</span>
<span class="doccomment">/// &quot;l/K/N&quot;</span>
<span class="doccomment">/// &quot;r/N&quot;</span>
<span class="doccomment">/// &quot;r/K/N&quot;</span>
<span class="doccomment">/// ```</span>
<span class="doccomment">///</span>
<span class="doccomment">/// The `N` represents the number of chunks and the `K` represents</span>
<span class="doccomment">/// a chunk number.</span>
<span class="doccomment">///</span>
<span class="doccomment">/// # Errors</span>
<span class="doccomment">///</span>
<span class="doccomment">/// If the string is not one of the valid number types, if `K` is</span>
<span class="doccomment">/// not a nonnegative integer, or if `N` is not a positive</span>
<span class="doccomment">/// integer, then this function returns [`NumberTypeError`].</span>
<span class="kw">fn</span> <span class="ident">from</span>(<span class="ident">s</span>: <span class="kw-2">&amp;</span><span class="ident">str</span>) -&gt; <span class="prelude-ty">Result</span><span class="op">&lt;</span><span class="self">Self</span>, <span class="ident">NumberTypeError</span><span class="op">&gt;</span> {
<span class="kw">let</span> <span class="ident">parts</span>: <span class="ident">Vec</span><span class="op">&lt;</span><span class="kw-2">&amp;</span><span class="ident">str</span><span class="op">&gt;</span> <span class="op">=</span> <span class="ident">s</span>.<span class="ident">split</span>(<span class="string">&#39;/&#39;</span>).<span class="ident">collect</span>();
<span class="kw">match</span> <span class="kw-2">&amp;</span><span class="ident">parts</span>[..] {
[<span class="ident">n_str</span>] =&gt; {
<span class="kw">let</span> <span class="ident">num_chunks</span> <span class="op">=</span> <span class="ident">n_str</span>
.<span class="ident">parse</span>()
.<span class="ident">map_err</span>(<span class="op">|</span><span class="kw">_</span><span class="op">|</span> <span class="ident">NumberTypeError::NumberOfChunks</span>(<span class="ident">n_str</span>.<span class="ident">to_string</span>()))<span class="question-mark">?</span>;
<span class="prelude-val">Ok</span>(<span class="ident"><span class="self">Self</span>::Bytes</span>(<span class="ident">num_chunks</span>))
}
[<span class="string">&quot;l&quot;</span>, <span class="ident">n_str</span>] =&gt; {
<span class="kw">let</span> <span class="ident">num_chunks</span> <span class="op">=</span> <span class="ident">n_str</span>
.<span class="ident">parse</span>()
.<span class="ident">map_err</span>(<span class="op">|</span><span class="kw">_</span><span class="op">|</span> <span class="ident">NumberTypeError::NumberOfChunks</span>(<span class="ident">n_str</span>.<span class="ident">to_string</span>()))<span class="question-mark">?</span>;
<span class="prelude-val">Ok</span>(<span class="ident"><span class="self">Self</span>::Lines</span>(<span class="ident">num_chunks</span>))
}
[<span class="string">&quot;l&quot;</span>, <span class="ident">k_str</span>, <span class="ident">n_str</span>] =&gt; {
<span class="kw">let</span> <span class="ident">num_chunks</span> <span class="op">=</span> <span class="ident">n_str</span>
.<span class="ident">parse</span>()
.<span class="ident">map_err</span>(<span class="op">|</span><span class="kw">_</span><span class="op">|</span> <span class="ident">NumberTypeError::NumberOfChunks</span>(<span class="ident">n_str</span>.<span class="ident">to_string</span>()))<span class="question-mark">?</span>;
<span class="kw">let</span> <span class="ident">chunk_number</span> <span class="op">=</span> <span class="ident">k_str</span>
.<span class="ident">parse</span>()
.<span class="ident">map_err</span>(<span class="op">|</span><span class="kw">_</span><span class="op">|</span> <span class="ident">NumberTypeError::ChunkNumber</span>(<span class="ident">k_str</span>.<span class="ident">to_string</span>()))<span class="question-mark">?</span>;
<span class="prelude-val">Ok</span>(<span class="ident"><span class="self">Self</span>::KthLines</span>(<span class="ident">chunk_number</span>, <span class="ident">num_chunks</span>))
}
[<span class="string">&quot;r&quot;</span>, <span class="ident">n_str</span>] =&gt; {
<span class="kw">let</span> <span class="ident">num_chunks</span> <span class="op">=</span> <span class="ident">n_str</span>
.<span class="ident">parse</span>()
.<span class="ident">map_err</span>(<span class="op">|</span><span class="kw">_</span><span class="op">|</span> <span class="ident">NumberTypeError::NumberOfChunks</span>(<span class="ident">n_str</span>.<span class="ident">to_string</span>()))<span class="question-mark">?</span>;
<span class="prelude-val">Ok</span>(<span class="ident"><span class="self">Self</span>::RoundRobin</span>(<span class="ident">num_chunks</span>))
}
[<span class="string">&quot;r&quot;</span>, <span class="ident">k_str</span>, <span class="ident">n_str</span>] =&gt; {
<span class="kw">let</span> <span class="ident">num_chunks</span> <span class="op">=</span> <span class="ident">n_str</span>
.<span class="ident">parse</span>()
.<span class="ident">map_err</span>(<span class="op">|</span><span class="kw">_</span><span class="op">|</span> <span class="ident">NumberTypeError::NumberOfChunks</span>(<span class="ident">n_str</span>.<span class="ident">to_string</span>()))<span class="question-mark">?</span>;
<span class="kw">let</span> <span class="ident">chunk_number</span> <span class="op">=</span> <span class="ident">k_str</span>
.<span class="ident">parse</span>()
.<span class="ident">map_err</span>(<span class="op">|</span><span class="kw">_</span><span class="op">|</span> <span class="ident">NumberTypeError::ChunkNumber</span>(<span class="ident">k_str</span>.<span class="ident">to_string</span>()))<span class="question-mark">?</span>;
<span class="prelude-val">Ok</span>(<span class="ident"><span class="self">Self</span>::KthRoundRobin</span>(<span class="ident">chunk_number</span>, <span class="ident">num_chunks</span>))
}
<span class="kw">_</span> =&gt; <span class="prelude-val">Err</span>(<span class="ident">NumberTypeError::NumberOfChunks</span>(<span class="ident">s</span>.<span class="ident">to_string</span>())),
}
}
}
<span class="doccomment">/// The strategy for breaking up the input file into chunks.</span>
<span class="kw">enum</span> <span class="ident">Strategy</span> {
<span class="doccomment">/// Each chunk has the specified number of lines.</span>
<span class="ident">Lines</span>(<span class="ident">u64</span>),
<span class="doccomment">/// Each chunk has the specified number of bytes.</span>
<span class="ident">Bytes</span>(<span class="ident">u64</span>),
<span class="doccomment">/// Each chunk has as many lines as possible without exceeding the</span>
<span class="doccomment">/// specified number of bytes.</span>
<span class="ident">LineBytes</span>(<span class="ident">u64</span>),
<span class="doccomment">/// Split the file into this many chunks.</span>
<span class="doccomment">///</span>
<span class="doccomment">/// There are several sub-strategies available, as defined by</span>
<span class="doccomment">/// [`NumberType`].</span>
<span class="ident">Number</span>(<span class="ident">NumberType</span>),
}
<span class="doccomment">/// An error when parsing a chunking strategy from command-line arguments.</span>
<span class="kw">enum</span> <span class="ident">StrategyError</span> {
<span class="doccomment">/// Invalid number of lines.</span>
<span class="ident">Lines</span>(<span class="ident">ParseSizeError</span>),
<span class="doccomment">/// Invalid number of bytes.</span>
<span class="ident">Bytes</span>(<span class="ident">ParseSizeError</span>),
<span class="doccomment">/// Invalid number type.</span>
<span class="ident">NumberType</span>(<span class="ident">NumberTypeError</span>),
<span class="doccomment">/// Multiple chunking strategies were specified (but only one should be).</span>
<span class="ident">MultipleWays</span>,
}
<span class="kw">impl</span> <span class="ident">fmt::Display</span> <span class="kw">for</span> <span class="ident">StrategyError</span> {
<span class="kw">fn</span> <span class="ident">fmt</span>(<span class="kw-2">&amp;</span><span class="self">self</span>, <span class="ident">f</span>: <span class="kw-2">&amp;mut</span> <span class="ident">fmt::Formatter</span>) -&gt; <span class="ident">fmt::Result</span> {
<span class="kw">match</span> <span class="self">self</span> {
<span class="ident"><span class="self">Self</span>::Lines</span>(<span class="ident">e</span>) =&gt; <span class="macro">write!</span>(<span class="ident">f</span>, <span class="string">&quot;invalid number of lines: {}&quot;</span>, <span class="ident">e</span>),
<span class="ident"><span class="self">Self</span>::Bytes</span>(<span class="ident">e</span>) =&gt; <span class="macro">write!</span>(<span class="ident">f</span>, <span class="string">&quot;invalid number of bytes: {}&quot;</span>, <span class="ident">e</span>),
<span class="ident"><span class="self">Self</span>::NumberType</span>(<span class="ident">NumberTypeError::NumberOfChunks</span>(<span class="ident">s</span>)) =&gt; {
<span class="macro">write!</span>(<span class="ident">f</span>, <span class="string">&quot;invalid number of chunks: {}&quot;</span>, <span class="ident">s</span>)
}
<span class="ident"><span class="self">Self</span>::NumberType</span>(<span class="ident">NumberTypeError::ChunkNumber</span>(<span class="ident">s</span>)) =&gt; {
<span class="macro">write!</span>(<span class="ident">f</span>, <span class="string">&quot;invalid chunk number: {}&quot;</span>, <span class="ident">s</span>)
}
<span class="ident"><span class="self">Self</span>::MultipleWays</span> =&gt; <span class="macro">write!</span>(<span class="ident">f</span>, <span class="string">&quot;cannot split in more than one way&quot;</span>),
}
}
}
<span class="kw">impl</span> <span class="ident">Strategy</span> {
<span class="doccomment">/// Parse a strategy from the command-line arguments.</span>
<span class="kw">fn</span> <span class="ident">from</span>(<span class="ident">matches</span>: <span class="kw-2">&amp;</span><span class="ident">ArgMatches</span>) -&gt; <span class="prelude-ty">Result</span><span class="op">&lt;</span><span class="self">Self</span>, <span class="ident">StrategyError</span><span class="op">&gt;</span> {
<span class="comment">// Check that the user is not specifying more than one strategy.</span>
<span class="comment">//</span>
<span class="comment">// Note: right now, this exact behavior cannot be handled by</span>
<span class="comment">// `ArgGroup` since `ArgGroup` considers a default value `Arg`</span>
<span class="comment">// as &quot;defined&quot;.</span>
<span class="kw">match</span> (
<span class="ident">matches</span>.<span class="ident">value_source</span>(<span class="ident">OPT_LINES</span>) <span class="op">==</span> <span class="prelude-val">Some</span>(<span class="ident">ValueSource::CommandLine</span>),
<span class="ident">matches</span>.<span class="ident">value_source</span>(<span class="ident">OPT_BYTES</span>) <span class="op">==</span> <span class="prelude-val">Some</span>(<span class="ident">ValueSource::CommandLine</span>),
<span class="ident">matches</span>.<span class="ident">value_source</span>(<span class="ident">OPT_LINE_BYTES</span>) <span class="op">==</span> <span class="prelude-val">Some</span>(<span class="ident">ValueSource::CommandLine</span>),
<span class="ident">matches</span>.<span class="ident">value_source</span>(<span class="ident">OPT_NUMBER</span>) <span class="op">==</span> <span class="prelude-val">Some</span>(<span class="ident">ValueSource::CommandLine</span>),
) {
(<span class="bool-val">false</span>, <span class="bool-val">false</span>, <span class="bool-val">false</span>, <span class="bool-val">false</span>) =&gt; <span class="prelude-val">Ok</span>(<span class="ident"><span class="self">Self</span>::Lines</span>(<span class="number">1000</span>)),
(<span class="bool-val">true</span>, <span class="bool-val">false</span>, <span class="bool-val">false</span>, <span class="bool-val">false</span>) =&gt; {
<span class="kw">let</span> <span class="ident">s</span> <span class="op">=</span> <span class="ident">matches</span>.<span class="ident">get_one</span>::<span class="op">&lt;</span><span class="ident">String</span><span class="op">&gt;</span>(<span class="ident">OPT_LINES</span>).<span class="ident">unwrap</span>();
<span class="kw">let</span> <span class="ident">n</span> <span class="op">=</span> <span class="ident">parse_size</span>(<span class="ident">s</span>).<span class="ident">map_err</span>(<span class="ident">StrategyError::Lines</span>)<span class="question-mark">?</span>;
<span class="prelude-val">Ok</span>(<span class="ident"><span class="self">Self</span>::Lines</span>(<span class="ident">n</span>))
}
(<span class="bool-val">false</span>, <span class="bool-val">true</span>, <span class="bool-val">false</span>, <span class="bool-val">false</span>) =&gt; {
<span class="kw">let</span> <span class="ident">s</span> <span class="op">=</span> <span class="ident">matches</span>.<span class="ident">get_one</span>::<span class="op">&lt;</span><span class="ident">String</span><span class="op">&gt;</span>(<span class="ident">OPT_BYTES</span>).<span class="ident">unwrap</span>();
<span class="kw">let</span> <span class="ident">n</span> <span class="op">=</span> <span class="ident">parse_size</span>(<span class="ident">s</span>).<span class="ident">map_err</span>(<span class="ident">StrategyError::Bytes</span>)<span class="question-mark">?</span>;
<span class="prelude-val">Ok</span>(<span class="ident"><span class="self">Self</span>::Bytes</span>(<span class="ident">n</span>))
}
(<span class="bool-val">false</span>, <span class="bool-val">false</span>, <span class="bool-val">true</span>, <span class="bool-val">false</span>) =&gt; {
<span class="kw">let</span> <span class="ident">s</span> <span class="op">=</span> <span class="ident">matches</span>.<span class="ident">get_one</span>::<span class="op">&lt;</span><span class="ident">String</span><span class="op">&gt;</span>(<span class="ident">OPT_LINE_BYTES</span>).<span class="ident">unwrap</span>();
<span class="kw">let</span> <span class="ident">n</span> <span class="op">=</span> <span class="ident">parse_size</span>(<span class="ident">s</span>).<span class="ident">map_err</span>(<span class="ident">StrategyError::Bytes</span>)<span class="question-mark">?</span>;
<span class="prelude-val">Ok</span>(<span class="ident"><span class="self">Self</span>::LineBytes</span>(<span class="ident">n</span>))
}
(<span class="bool-val">false</span>, <span class="bool-val">false</span>, <span class="bool-val">false</span>, <span class="bool-val">true</span>) =&gt; {
<span class="kw">let</span> <span class="ident">s</span> <span class="op">=</span> <span class="ident">matches</span>.<span class="ident">get_one</span>::<span class="op">&lt;</span><span class="ident">String</span><span class="op">&gt;</span>(<span class="ident">OPT_NUMBER</span>).<span class="ident">unwrap</span>();
<span class="kw">let</span> <span class="ident">number_type</span> <span class="op">=</span> <span class="ident">NumberType::from</span>(<span class="ident">s</span>).<span class="ident">map_err</span>(<span class="ident">StrategyError::NumberType</span>)<span class="question-mark">?</span>;
<span class="prelude-val">Ok</span>(<span class="ident"><span class="self">Self</span>::Number</span>(<span class="ident">number_type</span>))
}
<span class="kw">_</span> =&gt; <span class="prelude-val">Err</span>(<span class="ident">StrategyError::MultipleWays</span>),
}
}
}
<span class="doccomment">/// Parse the suffix type from the command-line arguments.</span>
<span class="kw">fn</span> <span class="ident">suffix_type_from</span>(<span class="ident">matches</span>: <span class="kw-2">&amp;</span><span class="ident">ArgMatches</span>) -&gt; <span class="prelude-ty">Result</span><span class="op">&lt;</span>(<span class="ident">SuffixType</span>, <span class="ident">usize</span>), <span class="ident">SettingsError</span><span class="op">&gt;</span> {
<span class="kw">if</span> <span class="ident">matches</span>.<span class="ident">value_source</span>(<span class="ident">OPT_NUMERIC_SUFFIXES</span>) <span class="op">==</span> <span class="prelude-val">Some</span>(<span class="ident">ValueSource::CommandLine</span>) {
<span class="kw">let</span> <span class="ident">suffix_start</span> <span class="op">=</span> <span class="ident">matches</span>.<span class="ident">value_of</span>(<span class="ident">OPT_NUMERIC_SUFFIXES</span>);
<span class="kw">let</span> <span class="ident">suffix_start</span> <span class="op">=</span> <span class="ident">suffix_start</span>.<span class="ident">ok_or</span>(<span class="ident">SettingsError::SuffixNotParsable</span>(<span class="ident">String::new</span>()))<span class="question-mark">?</span>;
<span class="kw">let</span> <span class="ident">suffix_start</span> <span class="op">=</span> <span class="ident">suffix_start</span>
.<span class="ident">parse</span>()
.<span class="ident">map_err</span>(<span class="op">|</span><span class="kw">_</span><span class="op">|</span> <span class="ident">SettingsError::SuffixNotParsable</span>(<span class="ident">suffix_start</span>.<span class="ident">to_string</span>()))<span class="question-mark">?</span>;
<span class="prelude-val">Ok</span>((<span class="ident">SuffixType::Decimal</span>, <span class="ident">suffix_start</span>))
} <span class="kw">else</span> <span class="kw">if</span> <span class="ident">matches</span>.<span class="ident">value_source</span>(<span class="ident">OPT_HEX_SUFFIXES</span>) <span class="op">==</span> <span class="prelude-val">Some</span>(<span class="ident">ValueSource::CommandLine</span>) {
<span class="kw">let</span> <span class="ident">suffix_start</span> <span class="op">=</span> <span class="ident">matches</span>.<span class="ident">value_of</span>(<span class="ident">OPT_HEX_SUFFIXES</span>);
<span class="kw">let</span> <span class="ident">suffix_start</span> <span class="op">=</span> <span class="ident">suffix_start</span>.<span class="ident">ok_or</span>(<span class="ident">SettingsError::SuffixNotParsable</span>(<span class="ident">String::new</span>()))<span class="question-mark">?</span>;
<span class="kw">let</span> <span class="ident">suffix_start</span> <span class="op">=</span> <span class="ident">usize::from_str_radix</span>(<span class="ident">suffix_start</span>, <span class="number">16</span>)
.<span class="ident">map_err</span>(<span class="op">|</span><span class="kw">_</span><span class="op">|</span> <span class="ident">SettingsError::SuffixNotParsable</span>(<span class="ident">suffix_start</span>.<span class="ident">to_string</span>()))<span class="question-mark">?</span>;
<span class="prelude-val">Ok</span>((<span class="ident">SuffixType::Hexadecimal</span>, <span class="ident">suffix_start</span>))
} <span class="kw">else</span> {
<span class="comment">// no numeric/hex suffix</span>
<span class="prelude-val">Ok</span>((<span class="ident">SuffixType::Alphabetic</span>, <span class="number">0</span>))
}
}
<span class="doccomment">/// Parameters that control how a file gets split.</span>
<span class="doccomment">///</span>
<span class="doccomment">/// You can convert an [`ArgMatches`] instance into a [`Settings`]</span>
<span class="doccomment">/// instance by calling [`Settings::from`].</span>
<span class="kw">struct</span> <span class="ident">Settings</span> {
<span class="ident">prefix</span>: <span class="ident">String</span>,
<span class="ident">suffix_type</span>: <span class="ident">SuffixType</span>,
<span class="ident">suffix_length</span>: <span class="ident">usize</span>,
<span class="ident">suffix_start</span>: <span class="ident">usize</span>,
<span class="ident">additional_suffix</span>: <span class="ident">String</span>,
<span class="ident">input</span>: <span class="ident">String</span>,
<span class="doccomment">/// When supplied, a shell command to output to instead of xaa, xab …</span>
<span class="ident">filter</span>: <span class="prelude-ty">Option</span><span class="op">&lt;</span><span class="ident">String</span><span class="op">&gt;</span>,
<span class="ident">strategy</span>: <span class="ident">Strategy</span>,
<span class="ident">verbose</span>: <span class="ident">bool</span>,
<span class="doccomment">/// Whether to *not* produce empty files when using `-n`.</span>
<span class="doccomment">///</span>
<span class="doccomment">/// The `-n` command-line argument gives a specific number of</span>
<span class="doccomment">/// chunks into which the input files will be split. If the number</span>
<span class="doccomment">/// of chunks is greater than the number of bytes, and this is</span>
<span class="doccomment">/// `false`, then empty files will be created for the excess</span>
<span class="doccomment">/// chunks. If this is `false`, then empty files will not be</span>
<span class="doccomment">/// created.</span>
<span class="ident">elide_empty_files</span>: <span class="ident">bool</span>,
}
<span class="doccomment">/// An error when parsing settings from command-line arguments.</span>
<span class="kw">enum</span> <span class="ident">SettingsError</span> {
<span class="doccomment">/// Invalid chunking strategy.</span>
<span class="ident">Strategy</span>(<span class="ident">StrategyError</span>),
<span class="doccomment">/// Invalid suffix length parameter.</span>
<span class="ident">SuffixNotParsable</span>(<span class="ident">String</span>),
<span class="doccomment">/// Suffix contains a directory separator, which is not allowed.</span>
<span class="ident">SuffixContainsSeparator</span>(<span class="ident">String</span>),
<span class="doccomment">/// Suffix is not large enough to split into specified chunks</span>
<span class="ident">SuffixTooSmall</span>(<span class="ident">usize</span>),
<span class="doccomment">/// The `--filter` option is not supported on Windows.</span>
<span class="attribute">#[<span class="ident">cfg</span>(<span class="ident">windows</span>)]</span>
<span class="ident">NotSupported</span>,
}
<span class="kw">impl</span> <span class="ident">SettingsError</span> {
<span class="doccomment">/// Whether the error demands a usage message.</span>
<span class="kw">fn</span> <span class="ident">requires_usage</span>(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; <span class="ident">bool</span> {
<span class="macro">matches!</span>(
<span class="self">self</span>,
<span class="ident"><span class="self">Self</span>::Strategy</span>(<span class="ident">StrategyError::MultipleWays</span>) <span class="op">|</span> <span class="ident"><span class="self">Self</span>::SuffixContainsSeparator</span>(<span class="kw">_</span>)
)
}
}
<span class="kw">impl</span> <span class="ident">fmt::Display</span> <span class="kw">for</span> <span class="ident">SettingsError</span> {
<span class="kw">fn</span> <span class="ident">fmt</span>(<span class="kw-2">&amp;</span><span class="self">self</span>, <span class="ident">f</span>: <span class="kw-2">&amp;mut</span> <span class="ident">fmt::Formatter</span>) -&gt; <span class="ident">fmt::Result</span> {
<span class="kw">match</span> <span class="self">self</span> {
<span class="ident"><span class="self">Self</span>::Strategy</span>(<span class="ident">e</span>) =&gt; <span class="ident">e</span>.<span class="ident">fmt</span>(<span class="ident">f</span>),
<span class="ident"><span class="self">Self</span>::SuffixNotParsable</span>(<span class="ident">s</span>) =&gt; <span class="macro">write!</span>(<span class="ident">f</span>, <span class="string">&quot;invalid suffix length: {}&quot;</span>, <span class="ident">s</span>.<span class="ident">quote</span>()),
<span class="ident"><span class="self">Self</span>::SuffixTooSmall</span>(<span class="ident">i</span>) =&gt; <span class="macro">write!</span>(<span class="ident">f</span>, <span class="string">&quot;the suffix length needs to be at least {}&quot;</span>, <span class="ident">i</span>),
<span class="ident"><span class="self">Self</span>::SuffixContainsSeparator</span>(<span class="ident">s</span>) =&gt; <span class="macro">write!</span>(
<span class="ident">f</span>,
<span class="string">&quot;invalid suffix {}, contains directory separator&quot;</span>,
<span class="ident">s</span>.<span class="ident">quote</span>()
),
<span class="attribute">#[<span class="ident">cfg</span>(<span class="ident">windows</span>)]</span>
<span class="ident"><span class="self">Self</span>::NotSupported</span> =&gt; <span class="macro">write!</span>(
<span class="ident">f</span>,
<span class="string">&quot;{} is currently not supported in this platform&quot;</span>,
<span class="ident">OPT_FILTER</span>
),
}
}
}
<span class="kw">impl</span> <span class="ident">Settings</span> {
<span class="doccomment">/// Parse a strategy from the command-line arguments.</span>
<span class="kw">fn</span> <span class="ident">from</span>(<span class="ident">matches</span>: <span class="kw-2">&amp;</span><span class="ident">ArgMatches</span>) -&gt; <span class="prelude-ty">Result</span><span class="op">&lt;</span><span class="self">Self</span>, <span class="ident">SettingsError</span><span class="op">&gt;</span> {
<span class="kw">let</span> <span class="ident">additional_suffix</span> <span class="op">=</span> <span class="ident">matches</span>
.<span class="ident">get_one</span>::<span class="op">&lt;</span><span class="ident">String</span><span class="op">&gt;</span>(<span class="ident">OPT_ADDITIONAL_SUFFIX</span>)
.<span class="ident">unwrap</span>()
.<span class="ident">to_string</span>();
<span class="kw">if</span> <span class="ident">additional_suffix</span>.<span class="ident">contains</span>(<span class="string">&#39;/&#39;</span>) {
<span class="kw">return</span> <span class="prelude-val">Err</span>(<span class="ident">SettingsError::SuffixContainsSeparator</span>(<span class="ident">additional_suffix</span>));
}
<span class="kw">let</span> <span class="ident">strategy</span> <span class="op">=</span> <span class="ident">Strategy::from</span>(<span class="ident">matches</span>).<span class="ident">map_err</span>(<span class="ident">SettingsError::Strategy</span>)<span class="question-mark">?</span>;
<span class="kw">let</span> (<span class="ident">suffix_type</span>, <span class="ident">suffix_start</span>) <span class="op">=</span> <span class="ident">suffix_type_from</span>(<span class="ident">matches</span>)<span class="question-mark">?</span>;
<span class="kw">let</span> <span class="ident">suffix_length_str</span> <span class="op">=</span> <span class="ident">matches</span>.<span class="ident">get_one</span>::<span class="op">&lt;</span><span class="ident">String</span><span class="op">&gt;</span>(<span class="ident">OPT_SUFFIX_LENGTH</span>).<span class="ident">unwrap</span>();
<span class="kw">let</span> <span class="ident">suffix_length</span>: <span class="ident">usize</span> <span class="op">=</span> <span class="ident">suffix_length_str</span>
.<span class="ident">parse</span>()
.<span class="ident">map_err</span>(<span class="op">|</span><span class="kw">_</span><span class="op">|</span> <span class="ident">SettingsError::SuffixNotParsable</span>(<span class="ident">suffix_length_str</span>.<span class="ident">to_string</span>()))<span class="question-mark">?</span>;
<span class="kw">if</span> <span class="kw">let</span> <span class="ident">Strategy::Number</span>(<span class="kw-2">ref</span> <span class="ident">number_type</span>) <span class="op">=</span> <span class="ident">strategy</span> {
<span class="kw">let</span> <span class="ident">chunks</span> <span class="op">=</span> <span class="ident">number_type</span>.<span class="ident">num_chunks</span>();
<span class="kw">if</span> <span class="ident">suffix_length</span> <span class="op">!</span><span class="op">=</span> <span class="number">0</span> {
<span class="kw">let</span> <span class="ident">required_suffix_length</span> <span class="op">=</span>
(<span class="ident">chunks</span> <span class="kw">as</span> <span class="ident">f64</span>).<span class="ident">log</span>(<span class="ident">suffix_type</span>.<span class="ident">radix</span>() <span class="kw">as</span> <span class="ident">f64</span>).<span class="ident">ceil</span>() <span class="kw">as</span> <span class="ident">usize</span>;
<span class="kw">if</span> <span class="ident">suffix_length</span> <span class="op">&lt;</span> <span class="ident">required_suffix_length</span> {
<span class="kw">return</span> <span class="prelude-val">Err</span>(<span class="ident">SettingsError::SuffixTooSmall</span>(<span class="ident">required_suffix_length</span>));
}
}
}
<span class="kw">let</span> <span class="ident">result</span> <span class="op">=</span> <span class="self">Self</span> {
<span class="ident">suffix_length</span>: <span class="ident">suffix_length_str</span>
.<span class="ident">parse</span>()
.<span class="ident">map_err</span>(<span class="op">|</span><span class="kw">_</span><span class="op">|</span> <span class="ident">SettingsError::SuffixNotParsable</span>(<span class="ident">suffix_length_str</span>.<span class="ident">to_string</span>()))<span class="question-mark">?</span>,
<span class="ident">suffix_type</span>,
<span class="ident">suffix_start</span>,
<span class="ident">additional_suffix</span>,
<span class="ident">verbose</span>: <span class="ident">matches</span>.<span class="ident">value_source</span>(<span class="string">&quot;verbose&quot;</span>) <span class="op">==</span> <span class="prelude-val">Some</span>(<span class="ident">ValueSource::CommandLine</span>),
<span class="ident">strategy</span>,
<span class="ident">input</span>: <span class="ident">matches</span>.<span class="ident">get_one</span>::<span class="op">&lt;</span><span class="ident">String</span><span class="op">&gt;</span>(<span class="ident">ARG_INPUT</span>).<span class="ident">unwrap</span>().<span class="ident">to_owned</span>(),
<span class="ident">prefix</span>: <span class="ident">matches</span>.<span class="ident">get_one</span>::<span class="op">&lt;</span><span class="ident">String</span><span class="op">&gt;</span>(<span class="ident">ARG_PREFIX</span>).<span class="ident">unwrap</span>().<span class="ident">to_owned</span>(),
<span class="ident">filter</span>: <span class="ident">matches</span>.<span class="ident">get_one</span>::<span class="op">&lt;</span><span class="ident">String</span><span class="op">&gt;</span>(<span class="ident">OPT_FILTER</span>).<span class="ident">map</span>(<span class="op">|</span><span class="ident">s</span><span class="op">|</span> <span class="ident">s</span>.<span class="ident">to_owned</span>()),
<span class="ident">elide_empty_files</span>: <span class="ident">matches</span>.<span class="ident">contains_id</span>(<span class="ident">OPT_ELIDE_EMPTY_FILES</span>),
};
<span class="attribute">#[<span class="ident">cfg</span>(<span class="ident">windows</span>)]</span>
<span class="kw">if</span> <span class="ident">result</span>.<span class="ident">filter</span>.<span class="ident">is_some</span>() {
<span class="comment">// see https://github.com/rust-lang/rust/issues/29494</span>
<span class="kw">return</span> <span class="prelude-val">Err</span>(<span class="ident">SettingsError::NotSupported</span>);
}
<span class="prelude-val">Ok</span>(<span class="ident">result</span>)
}
<span class="kw">fn</span> <span class="ident">instantiate_current_writer</span>(<span class="kw-2">&amp;</span><span class="self">self</span>, <span class="ident">filename</span>: <span class="kw-2">&amp;</span><span class="ident">str</span>) -&gt; <span class="ident">io::Result</span><span class="op">&lt;</span><span class="ident">BufWriter</span><span class="op">&lt;</span><span class="ident">Box</span><span class="op">&lt;</span><span class="kw">dyn</span> <span class="ident">Write</span><span class="op">&gt;</span><span class="op">&gt;</span><span class="op">&gt;</span> {
<span class="kw">if</span> <span class="ident">platform::paths_refer_to_same_file</span>(<span class="kw-2">&amp;</span><span class="self">self</span>.<span class="ident">input</span>, <span class="ident">filename</span>) {
<span class="kw">return</span> <span class="prelude-val">Err</span>(<span class="ident">io::Error::new</span>(
<span class="ident">ErrorKind::Other</span>,
<span class="macro">format!</span>(<span class="string">&quot;&#39;{}&#39; would overwrite input; aborting&quot;</span>, <span class="ident">filename</span>),
));
}
<span class="ident">platform::instantiate_current_writer</span>(<span class="kw-2">&amp;</span><span class="self">self</span>.<span class="ident">filter</span>, <span class="ident">filename</span>)
}
}
<span class="doccomment">/// Write a certain number of bytes to one file, then move on to another one.</span>
<span class="doccomment">///</span>
<span class="doccomment">/// This struct maintains an underlying writer representing the</span>
<span class="doccomment">/// current chunk of the output. If a call to [`write`] would cause</span>
<span class="doccomment">/// the underlying writer to write more than the allowed number of</span>
<span class="doccomment">/// bytes, a new writer is created and the excess bytes are written to</span>
<span class="doccomment">/// that one instead. As many new underlying writers are created as</span>
<span class="doccomment">/// needed to write all the bytes in the input buffer.</span>
<span class="kw">struct</span> <span class="ident">ByteChunkWriter</span><span class="op">&lt;</span><span class="lifetime">&#39;a</span><span class="op">&gt;</span> {
<span class="doccomment">/// Parameters for creating the underlying writer for each new chunk.</span>
<span class="ident">settings</span>: <span class="kw-2">&amp;</span><span class="lifetime">&#39;a</span> <span class="ident">Settings</span>,
<span class="doccomment">/// The maximum number of bytes allowed for a single chunk of output.</span>
<span class="ident">chunk_size</span>: <span class="ident">u64</span>,
<span class="doccomment">/// Running total of number of chunks that have been completed.</span>
<span class="ident">num_chunks_written</span>: <span class="ident">u64</span>,
<span class="doccomment">/// Remaining capacity in number of bytes in the current chunk.</span>
<span class="doccomment">///</span>
<span class="doccomment">/// This number starts at `chunk_size` and decreases as bytes are</span>
<span class="doccomment">/// written. Once it reaches zero, a writer for a new chunk is</span>
<span class="doccomment">/// initialized and this number gets reset to `chunk_size`.</span>
<span class="ident">num_bytes_remaining_in_current_chunk</span>: <span class="ident">u64</span>,
<span class="doccomment">/// The underlying writer for the current chunk.</span>
<span class="doccomment">///</span>
<span class="doccomment">/// Once the number of bytes written to this writer exceeds</span>
<span class="doccomment">/// `chunk_size`, a new writer is initialized and assigned to this</span>
<span class="doccomment">/// field.</span>
<span class="ident">inner</span>: <span class="ident">BufWriter</span><span class="op">&lt;</span><span class="ident">Box</span><span class="op">&lt;</span><span class="kw">dyn</span> <span class="ident">Write</span><span class="op">&gt;</span><span class="op">&gt;</span>,
<span class="doccomment">/// Iterator that yields filenames for each chunk.</span>
<span class="ident">filename_iterator</span>: <span class="ident">FilenameIterator</span><span class="op">&lt;</span><span class="lifetime">&#39;a</span><span class="op">&gt;</span>,
}
<span class="kw">impl</span><span class="op">&lt;</span><span class="lifetime">&#39;a</span><span class="op">&gt;</span> <span class="ident">ByteChunkWriter</span><span class="op">&lt;</span><span class="lifetime">&#39;a</span><span class="op">&gt;</span> {
<span class="kw">fn</span> <span class="ident">new</span>(<span class="ident">chunk_size</span>: <span class="ident">u64</span>, <span class="ident">settings</span>: <span class="kw-2">&amp;</span><span class="lifetime">&#39;a</span> <span class="ident">Settings</span>) -&gt; <span class="ident">UResult</span><span class="op">&lt;</span><span class="ident">ByteChunkWriter</span><span class="op">&lt;</span><span class="lifetime">&#39;a</span><span class="op">&gt;</span><span class="op">&gt;</span> {
<span class="kw">let</span> <span class="kw-2">mut</span> <span class="ident">filename_iterator</span> <span class="op">=</span> <span class="ident">FilenameIterator::new</span>(
<span class="kw-2">&amp;</span><span class="ident">settings</span>.<span class="ident">prefix</span>,
<span class="kw-2">&amp;</span><span class="ident">settings</span>.<span class="ident">additional_suffix</span>,
<span class="ident">settings</span>.<span class="ident">suffix_length</span>,
<span class="ident">settings</span>.<span class="ident">suffix_type</span>,
<span class="ident">settings</span>.<span class="ident">suffix_start</span>,
)<span class="question-mark">?</span>;
<span class="kw">let</span> <span class="ident">filename</span> <span class="op">=</span> <span class="ident">filename_iterator</span>
.<span class="ident">next</span>()
.<span class="ident">ok_or_else</span>(<span class="op">|</span><span class="op">|</span> <span class="ident">USimpleError::new</span>(<span class="number">1</span>, <span class="string">&quot;output file suffixes exhausted&quot;</span>))<span class="question-mark">?</span>;
<span class="kw">if</span> <span class="ident">settings</span>.<span class="ident">verbose</span> {
<span class="macro">println!</span>(<span class="string">&quot;creating file {}&quot;</span>, <span class="ident">filename</span>.<span class="ident">quote</span>());
}
<span class="kw">let</span> <span class="ident">inner</span> <span class="op">=</span> <span class="ident">settings</span>.<span class="ident">instantiate_current_writer</span>(<span class="kw-2">&amp;</span><span class="ident">filename</span>)<span class="question-mark">?</span>;
<span class="prelude-val">Ok</span>(<span class="ident">ByteChunkWriter</span> {
<span class="ident">settings</span>,
<span class="ident">chunk_size</span>,
<span class="ident">num_bytes_remaining_in_current_chunk</span>: <span class="ident">chunk_size</span>,
<span class="ident">num_chunks_written</span>: <span class="number">0</span>,
<span class="ident">inner</span>,
<span class="ident">filename_iterator</span>,
})
}
}
<span class="kw">impl</span><span class="op">&lt;</span><span class="lifetime">&#39;a</span><span class="op">&gt;</span> <span class="ident">Write</span> <span class="kw">for</span> <span class="ident">ByteChunkWriter</span><span class="op">&lt;</span><span class="lifetime">&#39;a</span><span class="op">&gt;</span> {
<span class="kw">fn</span> <span class="ident">write</span>(<span class="kw-2">&amp;mut</span> <span class="self">self</span>, <span class="kw-2">mut</span> <span class="ident">buf</span>: <span class="kw-2">&amp;</span>[<span class="ident">u8</span>]) -&gt; <span class="ident">std::io::Result</span><span class="op">&lt;</span><span class="ident">usize</span><span class="op">&gt;</span> {
<span class="comment">// If the length of `buf` exceeds the number of bytes remaining</span>
<span class="comment">// in the current chunk, we will need to write to multiple</span>
<span class="comment">// different underlying writers. In that case, each iteration of</span>
<span class="comment">// this loop writes to the underlying writer that corresponds to</span>
<span class="comment">// the current chunk number.</span>
<span class="kw">let</span> <span class="kw-2">mut</span> <span class="ident">carryover_bytes_written</span>: <span class="ident">usize</span> <span class="op">=</span> <span class="number">0</span>;
<span class="kw">loop</span> {
<span class="kw">if</span> <span class="ident">buf</span>.<span class="ident">is_empty</span>() {
<span class="kw">return</span> <span class="prelude-val">Ok</span>(<span class="ident">carryover_bytes_written</span>);
}
<span class="kw">if</span> <span class="self">self</span>.<span class="ident">num_bytes_remaining_in_current_chunk</span> <span class="op">==</span> <span class="number">0</span> {
<span class="comment">// Increment the chunk number, reset the number of bytes remaining, and instantiate the new underlying writer.</span>
<span class="self">self</span>.<span class="ident">num_chunks_written</span> <span class="op">+</span><span class="op">=</span> <span class="number">1</span>;
<span class="self">self</span>.<span class="ident">num_bytes_remaining_in_current_chunk</span> <span class="op">=</span> <span class="self">self</span>.<span class="ident">chunk_size</span>;
<span class="comment">// Allocate the new file, since at this point we know there are bytes to be written to it.</span>
<span class="kw">let</span> <span class="ident">filename</span> <span class="op">=</span> <span class="self">self</span>.<span class="ident">filename_iterator</span>.<span class="ident">next</span>().<span class="ident">ok_or_else</span>(<span class="op">|</span><span class="op">|</span> {
<span class="ident">std::io::Error::new</span>(<span class="ident">ErrorKind::Other</span>, <span class="string">&quot;output file suffixes exhausted&quot;</span>)
})<span class="question-mark">?</span>;
<span class="kw">if</span> <span class="self">self</span>.<span class="ident">settings</span>.<span class="ident">verbose</span> {
<span class="macro">println!</span>(<span class="string">&quot;creating file {}&quot;</span>, <span class="ident">filename</span>.<span class="ident">quote</span>());
}
<span class="self">self</span>.<span class="ident">inner</span> <span class="op">=</span> <span class="self">self</span>.<span class="ident">settings</span>.<span class="ident">instantiate_current_writer</span>(<span class="kw-2">&amp;</span><span class="ident">filename</span>)<span class="question-mark">?</span>;
}
<span class="comment">// If the capacity of this chunk is greater than the number of</span>
<span class="comment">// bytes in `buf`, then write all the bytes in `buf`. Otherwise,</span>
<span class="comment">// write enough bytes to fill the current chunk, then increment</span>
<span class="comment">// the chunk number and repeat.</span>
<span class="kw">let</span> <span class="ident">n</span> <span class="op">=</span> <span class="ident">buf</span>.<span class="ident">len</span>();
<span class="kw">if</span> (<span class="ident">n</span> <span class="kw">as</span> <span class="ident">u64</span>) <span class="op">&lt;</span> <span class="self">self</span>.<span class="ident">num_bytes_remaining_in_current_chunk</span> {
<span class="kw">let</span> <span class="ident">num_bytes_written</span> <span class="op">=</span> <span class="self">self</span>.<span class="ident">inner</span>.<span class="ident">write</span>(<span class="ident">buf</span>)<span class="question-mark">?</span>;
<span class="self">self</span>.<span class="ident">num_bytes_remaining_in_current_chunk</span> <span class="op">-</span><span class="op">=</span> <span class="ident">num_bytes_written</span> <span class="kw">as</span> <span class="ident">u64</span>;
<span class="kw">return</span> <span class="prelude-val">Ok</span>(<span class="ident">carryover_bytes_written</span> <span class="op">+</span> <span class="ident">num_bytes_written</span>);
} <span class="kw">else</span> {
<span class="comment">// Write enough bytes to fill the current chunk.</span>
<span class="comment">//</span>
<span class="comment">// Conversion to usize is safe because we checked that</span>
<span class="comment">// self.num_bytes_remaining_in_current_chunk is lower than</span>
<span class="comment">// n, which is already usize.</span>
<span class="kw">let</span> <span class="ident">i</span> <span class="op">=</span> <span class="self">self</span>.<span class="ident">num_bytes_remaining_in_current_chunk</span> <span class="kw">as</span> <span class="ident">usize</span>;
<span class="kw">let</span> <span class="ident">num_bytes_written</span> <span class="op">=</span> <span class="self">self</span>.<span class="ident">inner</span>.<span class="ident">write</span>(<span class="kw-2">&amp;</span><span class="ident">buf</span>[..<span class="ident">i</span>])<span class="question-mark">?</span>;
<span class="self">self</span>.<span class="ident">num_bytes_remaining_in_current_chunk</span> <span class="op">-</span><span class="op">=</span> <span class="ident">num_bytes_written</span> <span class="kw">as</span> <span class="ident">u64</span>;
<span class="comment">// It&#39;s possible that the underlying writer did not</span>
<span class="comment">// write all the bytes.</span>
<span class="kw">if</span> <span class="ident">num_bytes_written</span> <span class="op">&lt;</span> <span class="ident">i</span> {
<span class="kw">return</span> <span class="prelude-val">Ok</span>(<span class="ident">carryover_bytes_written</span> <span class="op">+</span> <span class="ident">num_bytes_written</span>);
} <span class="kw">else</span> {
<span class="comment">// Move the window to look at only the remaining bytes.</span>
<span class="ident">buf</span> <span class="op">=</span> <span class="kw-2">&amp;</span><span class="ident">buf</span>[<span class="ident">i</span>..];
<span class="comment">// Remember for the next iteration that we wrote these bytes.</span>
<span class="ident">carryover_bytes_written</span> <span class="op">+</span><span class="op">=</span> <span class="ident">num_bytes_written</span>;
}
}
}
}
<span class="kw">fn</span> <span class="ident">flush</span>(<span class="kw-2">&amp;mut</span> <span class="self">self</span>) -&gt; <span class="ident">std::io::Result</span><span class="op">&lt;</span>()<span class="op">&gt;</span> {
<span class="self">self</span>.<span class="ident">inner</span>.<span class="ident">flush</span>()
}
}
<span class="doccomment">/// Write a certain number of lines to one file, then move on to another one.</span>
<span class="doccomment">///</span>
<span class="doccomment">/// This struct maintains an underlying writer representing the</span>
<span class="doccomment">/// current chunk of the output. If a call to [`write`] would cause</span>
<span class="doccomment">/// the underlying writer to write more than the allowed number of</span>
<span class="doccomment">/// lines, a new writer is created and the excess lines are written to</span>
<span class="doccomment">/// that one instead. As many new underlying writers are created as</span>
<span class="doccomment">/// needed to write all the lines in the input buffer.</span>
<span class="kw">struct</span> <span class="ident">LineChunkWriter</span><span class="op">&lt;</span><span class="lifetime">&#39;a</span><span class="op">&gt;</span> {
<span class="doccomment">/// Parameters for creating the underlying writer for each new chunk.</span>
<span class="ident">settings</span>: <span class="kw-2">&amp;</span><span class="lifetime">&#39;a</span> <span class="ident">Settings</span>,
<span class="doccomment">/// The maximum number of lines allowed for a single chunk of output.</span>
<span class="ident">chunk_size</span>: <span class="ident">u64</span>,
<span class="doccomment">/// Running total of number of chunks that have been completed.</span>
<span class="ident">num_chunks_written</span>: <span class="ident">u64</span>,
<span class="doccomment">/// Remaining capacity in number of lines in the current chunk.</span>
<span class="doccomment">///</span>
<span class="doccomment">/// This number starts at `chunk_size` and decreases as lines are</span>
<span class="doccomment">/// written. Once it reaches zero, a writer for a new chunk is</span>
<span class="doccomment">/// initialized and this number gets reset to `chunk_size`.</span>
<span class="ident">num_lines_remaining_in_current_chunk</span>: <span class="ident">u64</span>,
<span class="doccomment">/// The underlying writer for the current chunk.</span>
<span class="doccomment">///</span>
<span class="doccomment">/// Once the number of lines written to this writer exceeds</span>
<span class="doccomment">/// `chunk_size`, a new writer is initialized and assigned to this</span>
<span class="doccomment">/// field.</span>
<span class="ident">inner</span>: <span class="ident">BufWriter</span><span class="op">&lt;</span><span class="ident">Box</span><span class="op">&lt;</span><span class="kw">dyn</span> <span class="ident">Write</span><span class="op">&gt;</span><span class="op">&gt;</span>,
<span class="doccomment">/// Iterator that yields filenames for each chunk.</span>
<span class="ident">filename_iterator</span>: <span class="ident">FilenameIterator</span><span class="op">&lt;</span><span class="lifetime">&#39;a</span><span class="op">&gt;</span>,
}
<span class="kw">impl</span><span class="op">&lt;</span><span class="lifetime">&#39;a</span><span class="op">&gt;</span> <span class="ident">LineChunkWriter</span><span class="op">&lt;</span><span class="lifetime">&#39;a</span><span class="op">&gt;</span> {
<span class="kw">fn</span> <span class="ident">new</span>(<span class="ident">chunk_size</span>: <span class="ident">u64</span>, <span class="ident">settings</span>: <span class="kw-2">&amp;</span><span class="lifetime">&#39;a</span> <span class="ident">Settings</span>) -&gt; <span class="ident">UResult</span><span class="op">&lt;</span><span class="ident">LineChunkWriter</span><span class="op">&lt;</span><span class="lifetime">&#39;a</span><span class="op">&gt;</span><span class="op">&gt;</span> {
<span class="kw">let</span> <span class="kw-2">mut</span> <span class="ident">filename_iterator</span> <span class="op">=</span> <span class="ident">FilenameIterator::new</span>(
<span class="kw-2">&amp;</span><span class="ident">settings</span>.<span class="ident">prefix</span>,
<span class="kw-2">&amp;</span><span class="ident">settings</span>.<span class="ident">additional_suffix</span>,
<span class="ident">settings</span>.<span class="ident">suffix_length</span>,
<span class="ident">settings</span>.<span class="ident">suffix_type</span>,
<span class="ident">settings</span>.<span class="ident">suffix_start</span>,
)<span class="question-mark">?</span>;
<span class="kw">let</span> <span class="ident">filename</span> <span class="op">=</span> <span class="ident">filename_iterator</span>
.<span class="ident">next</span>()
.<span class="ident">ok_or_else</span>(<span class="op">|</span><span class="op">|</span> <span class="ident">USimpleError::new</span>(<span class="number">1</span>, <span class="string">&quot;output file suffixes exhausted&quot;</span>))<span class="question-mark">?</span>;
<span class="kw">if</span> <span class="ident">settings</span>.<span class="ident">verbose</span> {
<span class="macro">println!</span>(<span class="string">&quot;creating file {}&quot;</span>, <span class="ident">filename</span>.<span class="ident">quote</span>());
}
<span class="kw">let</span> <span class="ident">inner</span> <span class="op">=</span> <span class="ident">settings</span>.<span class="ident">instantiate_current_writer</span>(<span class="kw-2">&amp;</span><span class="ident">filename</span>)<span class="question-mark">?</span>;
<span class="prelude-val">Ok</span>(<span class="ident">LineChunkWriter</span> {
<span class="ident">settings</span>,
<span class="ident">chunk_size</span>,
<span class="ident">num_lines_remaining_in_current_chunk</span>: <span class="ident">chunk_size</span>,
<span class="ident">num_chunks_written</span>: <span class="number">0</span>,
<span class="ident">inner</span>,
<span class="ident">filename_iterator</span>,
})
}
}
<span class="kw">impl</span><span class="op">&lt;</span><span class="lifetime">&#39;a</span><span class="op">&gt;</span> <span class="ident">Write</span> <span class="kw">for</span> <span class="ident">LineChunkWriter</span><span class="op">&lt;</span><span class="lifetime">&#39;a</span><span class="op">&gt;</span> {
<span class="kw">fn</span> <span class="ident">write</span>(<span class="kw-2">&amp;mut</span> <span class="self">self</span>, <span class="ident">buf</span>: <span class="kw-2">&amp;</span>[<span class="ident">u8</span>]) -&gt; <span class="ident">std::io::Result</span><span class="op">&lt;</span><span class="ident">usize</span><span class="op">&gt;</span> {
<span class="comment">// If the number of lines in `buf` exceeds the number of lines</span>
<span class="comment">// remaining in the current chunk, we will need to write to</span>
<span class="comment">// multiple different underlying writers. In that case, each</span>
<span class="comment">// iteration of this loop writes to the underlying writer that</span>
<span class="comment">// corresponds to the current chunk number.</span>
<span class="kw">let</span> <span class="kw-2">mut</span> <span class="ident">prev</span> <span class="op">=</span> <span class="number">0</span>;
<span class="kw">let</span> <span class="kw-2">mut</span> <span class="ident">total_bytes_written</span> <span class="op">=</span> <span class="number">0</span>;
<span class="kw">for</span> <span class="ident">i</span> <span class="kw">in</span> <span class="ident">memchr::memchr_iter</span>(<span class="string">b&#39;\n&#39;</span>, <span class="ident">buf</span>) {
<span class="comment">// If we have exceeded the number of lines to write in the</span>
<span class="comment">// current chunk, then start a new chunk and its</span>
<span class="comment">// corresponding writer.</span>
<span class="kw">if</span> <span class="self">self</span>.<span class="ident">num_lines_remaining_in_current_chunk</span> <span class="op">==</span> <span class="number">0</span> {
<span class="self">self</span>.<span class="ident">num_chunks_written</span> <span class="op">+</span><span class="op">=</span> <span class="number">1</span>;
<span class="kw">let</span> <span class="ident">filename</span> <span class="op">=</span> <span class="self">self</span>.<span class="ident">filename_iterator</span>.<span class="ident">next</span>().<span class="ident">ok_or_else</span>(<span class="op">|</span><span class="op">|</span> {
<span class="ident">std::io::Error::new</span>(<span class="ident">ErrorKind::Other</span>, <span class="string">&quot;output file suffixes exhausted&quot;</span>)
})<span class="question-mark">?</span>;
<span class="kw">if</span> <span class="self">self</span>.<span class="ident">settings</span>.<span class="ident">verbose</span> {
<span class="macro">println!</span>(<span class="string">&quot;creating file {}&quot;</span>, <span class="ident">filename</span>.<span class="ident">quote</span>());
}
<span class="self">self</span>.<span class="ident">inner</span> <span class="op">=</span> <span class="self">self</span>.<span class="ident">settings</span>.<span class="ident">instantiate_current_writer</span>(<span class="kw-2">&amp;</span><span class="ident">filename</span>)<span class="question-mark">?</span>;
<span class="self">self</span>.<span class="ident">num_lines_remaining_in_current_chunk</span> <span class="op">=</span> <span class="self">self</span>.<span class="ident">chunk_size</span>;
}
<span class="comment">// Write the line, starting from *after* the previous</span>
<span class="comment">// newline character and ending *after* the current</span>
<span class="comment">// newline character.</span>
<span class="kw">let</span> <span class="ident">n</span> <span class="op">=</span> <span class="self">self</span>.<span class="ident">inner</span>.<span class="ident">write</span>(<span class="kw-2">&amp;</span><span class="ident">buf</span>[<span class="ident">prev</span>..<span class="ident">i</span> <span class="op">+</span> <span class="number">1</span>])<span class="question-mark">?</span>;
<span class="ident">total_bytes_written</span> <span class="op">+</span><span class="op">=</span> <span class="ident">n</span>;
<span class="ident">prev</span> <span class="op">=</span> <span class="ident">i</span> <span class="op">+</span> <span class="number">1</span>;
<span class="self">self</span>.<span class="ident">num_lines_remaining_in_current_chunk</span> <span class="op">-</span><span class="op">=</span> <span class="number">1</span>;
}
<span class="kw">let</span> <span class="ident">n</span> <span class="op">=</span> <span class="self">self</span>.<span class="ident">inner</span>.<span class="ident">write</span>(<span class="kw-2">&amp;</span><span class="ident">buf</span>[<span class="ident">prev</span>..<span class="ident">buf</span>.<span class="ident">len</span>()])<span class="question-mark">?</span>;
<span class="ident">total_bytes_written</span> <span class="op">+</span><span class="op">=</span> <span class="ident">n</span>;
<span class="prelude-val">Ok</span>(<span class="ident">total_bytes_written</span>)
}
<span class="kw">fn</span> <span class="ident">flush</span>(<span class="kw-2">&amp;mut</span> <span class="self">self</span>) -&gt; <span class="ident">std::io::Result</span><span class="op">&lt;</span>()<span class="op">&gt;</span> {
<span class="self">self</span>.<span class="ident">inner</span>.<span class="ident">flush</span>()
}
}
<span class="doccomment">/// Write lines to each sequential output files, limited by bytes.</span>
<span class="doccomment">///</span>
<span class="doccomment">/// This struct maintains an underlying writer representing the</span>
<span class="doccomment">/// current chunk of the output. On each call to [`write`], it writes</span>
<span class="doccomment">/// as many lines as possible to the current chunk without exceeding</span>
<span class="doccomment">/// the specified byte limit. If a single line has more bytes than the</span>
<span class="doccomment">/// limit, then fill an entire single chunk with those bytes and</span>
<span class="doccomment">/// handle the remainder of the line as if it were its own distinct</span>
<span class="doccomment">/// line. As many new underlying writers are created as needed to</span>
<span class="doccomment">/// write all the data in the input buffer.</span>
<span class="kw">struct</span> <span class="ident">LineBytesChunkWriter</span><span class="op">&lt;</span><span class="lifetime">&#39;a</span><span class="op">&gt;</span> {
<span class="doccomment">/// Parameters for creating the underlying writer for each new chunk.</span>
<span class="ident">settings</span>: <span class="kw-2">&amp;</span><span class="lifetime">&#39;a</span> <span class="ident">Settings</span>,
<span class="doccomment">/// The maximum number of bytes allowed for a single chunk of output.</span>
<span class="ident">chunk_size</span>: <span class="ident">u64</span>,
<span class="doccomment">/// Running total of number of chunks that have been completed.</span>
<span class="ident">num_chunks_written</span>: <span class="ident">usize</span>,
<span class="doccomment">/// Remaining capacity in number of bytes in the current chunk.</span>
<span class="doccomment">///</span>
<span class="doccomment">/// This number starts at `chunk_size` and decreases as lines are</span>
<span class="doccomment">/// written. Once it reaches zero, a writer for a new chunk is</span>
<span class="doccomment">/// initialized and this number gets reset to `chunk_size`.</span>
<span class="ident">num_bytes_remaining_in_current_chunk</span>: <span class="ident">usize</span>,
<span class="doccomment">/// The underlying writer for the current chunk.</span>
<span class="doccomment">///</span>
<span class="doccomment">/// Once the number of bytes written to this writer exceeds</span>
<span class="doccomment">/// `chunk_size`, a new writer is initialized and assigned to this</span>
<span class="doccomment">/// field.</span>
<span class="ident">inner</span>: <span class="ident">BufWriter</span><span class="op">&lt;</span><span class="ident">Box</span><span class="op">&lt;</span><span class="kw">dyn</span> <span class="ident">Write</span><span class="op">&gt;</span><span class="op">&gt;</span>,
<span class="doccomment">/// Iterator that yields filenames for each chunk.</span>
<span class="ident">filename_iterator</span>: <span class="ident">FilenameIterator</span><span class="op">&lt;</span><span class="lifetime">&#39;a</span><span class="op">&gt;</span>,
}
<span class="kw">impl</span><span class="op">&lt;</span><span class="lifetime">&#39;a</span><span class="op">&gt;</span> <span class="ident">LineBytesChunkWriter</span><span class="op">&lt;</span><span class="lifetime">&#39;a</span><span class="op">&gt;</span> {
<span class="kw">fn</span> <span class="ident">new</span>(<span class="ident">chunk_size</span>: <span class="ident">u64</span>, <span class="ident">settings</span>: <span class="kw-2">&amp;</span><span class="lifetime">&#39;a</span> <span class="ident">Settings</span>) -&gt; <span class="ident">UResult</span><span class="op">&lt;</span><span class="ident">LineBytesChunkWriter</span><span class="op">&lt;</span><span class="lifetime">&#39;a</span><span class="op">&gt;</span><span class="op">&gt;</span> {
<span class="kw">let</span> <span class="kw-2">mut</span> <span class="ident">filename_iterator</span> <span class="op">=</span> <span class="ident">FilenameIterator::new</span>(
<span class="kw-2">&amp;</span><span class="ident">settings</span>.<span class="ident">prefix</span>,
<span class="kw-2">&amp;</span><span class="ident">settings</span>.<span class="ident">additional_suffix</span>,
<span class="ident">settings</span>.<span class="ident">suffix_length</span>,
<span class="ident">settings</span>.<span class="ident">suffix_type</span>,
<span class="ident">settings</span>.<span class="ident">suffix_start</span>,
)<span class="question-mark">?</span>;
<span class="kw">let</span> <span class="ident">filename</span> <span class="op">=</span> <span class="ident">filename_iterator</span>
.<span class="ident">next</span>()
.<span class="ident">ok_or_else</span>(<span class="op">|</span><span class="op">|</span> <span class="ident">USimpleError::new</span>(<span class="number">1</span>, <span class="string">&quot;output file suffixes exhausted&quot;</span>))<span class="question-mark">?</span>;
<span class="kw">if</span> <span class="ident">settings</span>.<span class="ident">verbose</span> {
<span class="macro">println!</span>(<span class="string">&quot;creating file {}&quot;</span>, <span class="ident">filename</span>.<span class="ident">quote</span>());
}
<span class="kw">let</span> <span class="ident">inner</span> <span class="op">=</span> <span class="ident">settings</span>.<span class="ident">instantiate_current_writer</span>(<span class="kw-2">&amp;</span><span class="ident">filename</span>)<span class="question-mark">?</span>;
<span class="prelude-val">Ok</span>(<span class="ident">LineBytesChunkWriter</span> {
<span class="ident">settings</span>,
<span class="ident">chunk_size</span>,
<span class="ident">num_bytes_remaining_in_current_chunk</span>: <span class="ident">usize::try_from</span>(<span class="ident">chunk_size</span>).<span class="ident">unwrap</span>(),
<span class="ident">num_chunks_written</span>: <span class="number">0</span>,
<span class="ident">inner</span>,
<span class="ident">filename_iterator</span>,
})
}
}
<span class="kw">impl</span><span class="op">&lt;</span><span class="lifetime">&#39;a</span><span class="op">&gt;</span> <span class="ident">Write</span> <span class="kw">for</span> <span class="ident">LineBytesChunkWriter</span><span class="op">&lt;</span><span class="lifetime">&#39;a</span><span class="op">&gt;</span> {
<span class="doccomment">/// Write as many lines to a chunk as possible without</span>
<span class="doccomment">/// exceeding the byte limit. If a single line has more bytes</span>
<span class="doccomment">/// than the limit, then fill an entire single chunk with those</span>
<span class="doccomment">/// bytes and handle the remainder of the line as if it were</span>
<span class="doccomment">/// its own distinct line.</span>
<span class="doccomment">///</span>
<span class="doccomment">/// For example: if the `chunk_size` is 8 and the input is:</span>
<span class="doccomment">///</span>
<span class="doccomment">/// ```text</span>
<span class="doccomment">/// aaaaaaaaa\nbbbb\ncccc\ndd\nee\n</span>
<span class="doccomment">/// ```</span>
<span class="doccomment">///</span>
<span class="doccomment">/// then the output gets broken into chunks like this:</span>
<span class="doccomment">///</span>
<span class="doccomment">/// ```text</span>
<span class="doccomment">/// chunk 0 chunk 1 chunk 2 chunk 3</span>
<span class="doccomment">///</span>
<span class="doccomment">/// 0 1 2</span>
<span class="doccomment">/// 01234567 89 01234 56789 012 345 6</span>
<span class="doccomment">/// |------| |-------| |--------| |---|</span>
<span class="doccomment">/// aaaaaaaa a\nbbbb\n cccc\ndd\n ee\n</span>
<span class="doccomment">/// ```</span>
<span class="kw">fn</span> <span class="ident">write</span>(<span class="kw-2">&amp;mut</span> <span class="self">self</span>, <span class="kw-2">mut</span> <span class="ident">buf</span>: <span class="kw-2">&amp;</span>[<span class="ident">u8</span>]) -&gt; <span class="ident">std::io::Result</span><span class="op">&lt;</span><span class="ident">usize</span><span class="op">&gt;</span> {
<span class="comment">// The total number of bytes written during the loop below.</span>
<span class="comment">//</span>
<span class="comment">// It is necessary to keep this running total because we may</span>
<span class="comment">// be making multiple calls to `write()` on multiple different</span>
<span class="comment">// underlying writers and we want the final reported number of</span>
<span class="comment">// bytes written to reflect the total number of bytes written</span>
<span class="comment">// to all of the underlying writers.</span>
<span class="kw">let</span> <span class="kw-2">mut</span> <span class="ident">total_bytes_written</span> <span class="op">=</span> <span class="number">0</span>;
<span class="comment">// Loop until we have written all bytes in the input buffer</span>
<span class="comment">// (or an IO error occurs).</span>
<span class="kw">loop</span> {
<span class="comment">// If the buffer is empty, then we are done writing.</span>
<span class="kw">if</span> <span class="ident">buf</span>.<span class="ident">is_empty</span>() {
<span class="kw">return</span> <span class="prelude-val">Ok</span>(<span class="ident">total_bytes_written</span>);
}
<span class="comment">// If we have filled the current chunk with bytes, then</span>
<span class="comment">// start a new chunk and initialize its corresponding</span>
<span class="comment">// writer.</span>
<span class="kw">if</span> <span class="self">self</span>.<span class="ident">num_bytes_remaining_in_current_chunk</span> <span class="op">==</span> <span class="number">0</span> {
<span class="self">self</span>.<span class="ident">num_chunks_written</span> <span class="op">+</span><span class="op">=</span> <span class="number">1</span>;
<span class="kw">let</span> <span class="ident">filename</span> <span class="op">=</span> <span class="self">self</span>.<span class="ident">filename_iterator</span>.<span class="ident">next</span>().<span class="ident">ok_or_else</span>(<span class="op">|</span><span class="op">|</span> {
<span class="ident">std::io::Error::new</span>(<span class="ident">ErrorKind::Other</span>, <span class="string">&quot;output file suffixes exhausted&quot;</span>)
})<span class="question-mark">?</span>;
<span class="kw">if</span> <span class="self">self</span>.<span class="ident">settings</span>.<span class="ident">verbose</span> {
<span class="macro">println!</span>(<span class="string">&quot;creating file {}&quot;</span>, <span class="ident">filename</span>.<span class="ident">quote</span>());
}
<span class="self">self</span>.<span class="ident">inner</span> <span class="op">=</span> <span class="self">self</span>.<span class="ident">settings</span>.<span class="ident">instantiate_current_writer</span>(<span class="kw-2">&amp;</span><span class="ident">filename</span>)<span class="question-mark">?</span>;
<span class="self">self</span>.<span class="ident">num_bytes_remaining_in_current_chunk</span> <span class="op">=</span> <span class="self">self</span>.<span class="ident">chunk_size</span>.<span class="ident">try_into</span>().<span class="ident">unwrap</span>();
}
<span class="comment">// Find the first newline character in the buffer.</span>
<span class="kw">match</span> <span class="ident">memchr::memchr</span>(<span class="string">b&#39;\n&#39;</span>, <span class="ident">buf</span>) {
<span class="comment">// If there is no newline character and the buffer is</span>
<span class="comment">// not empty, then write as many bytes as we can and</span>
<span class="comment">// then move on to the next chunk if necessary.</span>
<span class="prelude-val">None</span> =&gt; {
<span class="kw">let</span> <span class="ident">end</span> <span class="op">=</span> <span class="self">self</span>.<span class="ident">num_bytes_remaining_in_current_chunk</span>;
<span class="kw">let</span> <span class="ident">num_bytes_written</span> <span class="op">=</span> <span class="self">self</span>.<span class="ident">inner</span>.<span class="ident">write</span>(<span class="kw-2">&amp;</span><span class="ident">buf</span>[..<span class="ident">end</span>.<span class="ident">min</span>(<span class="ident">buf</span>.<span class="ident">len</span>())])<span class="question-mark">?</span>;
<span class="self">self</span>.<span class="ident">num_bytes_remaining_in_current_chunk</span> <span class="op">-</span><span class="op">=</span> <span class="ident">num_bytes_written</span>;
<span class="ident">total_bytes_written</span> <span class="op">+</span><span class="op">=</span> <span class="ident">num_bytes_written</span>;
<span class="ident">buf</span> <span class="op">=</span> <span class="kw-2">&amp;</span><span class="ident">buf</span>[<span class="ident">num_bytes_written</span>..];
}
<span class="comment">// If there is a newline character and the line</span>
<span class="comment">// (including the newline character) will fit in the</span>
<span class="comment">// current chunk, then write the entire line and</span>
<span class="comment">// continue to the next iteration. (See chunk 1 in the</span>
<span class="comment">// example comment above.)</span>
<span class="prelude-val">Some</span>(<span class="ident">i</span>) <span class="kw">if</span> <span class="ident">i</span> <span class="op">&lt;</span> <span class="self">self</span>.<span class="ident">num_bytes_remaining_in_current_chunk</span> =&gt; {
<span class="kw">let</span> <span class="ident">num_bytes_written</span> <span class="op">=</span> <span class="self">self</span>.<span class="ident">inner</span>.<span class="ident">write</span>(<span class="kw-2">&amp;</span><span class="ident">buf</span>[..<span class="ident">i</span> <span class="op">+</span> <span class="number">1</span>])<span class="question-mark">?</span>;
<span class="self">self</span>.<span class="ident">num_bytes_remaining_in_current_chunk</span> <span class="op">-</span><span class="op">=</span> <span class="ident">num_bytes_written</span>;
<span class="ident">total_bytes_written</span> <span class="op">+</span><span class="op">=</span> <span class="ident">num_bytes_written</span>;
<span class="ident">buf</span> <span class="op">=</span> <span class="kw-2">&amp;</span><span class="ident">buf</span>[<span class="ident">num_bytes_written</span>..];
}
<span class="comment">// If there is a newline character, the line</span>
<span class="comment">// (including the newline character) will not fit in</span>
<span class="comment">// the current chunk, *and* no other lines have been</span>
<span class="comment">// written to the current chunk, then write as many</span>
<span class="comment">// bytes as we can and continue to the next</span>
<span class="comment">// iteration. (See chunk 0 in the example comment</span>
<span class="comment">// above.)</span>
<span class="prelude-val">Some</span>(<span class="kw">_</span>)
<span class="kw">if</span> <span class="self">self</span>.<span class="ident">num_bytes_remaining_in_current_chunk</span>
<span class="op">==</span> <span class="self">self</span>.<span class="ident">chunk_size</span>.<span class="ident">try_into</span>().<span class="ident">unwrap</span>() =&gt;
{
<span class="kw">let</span> <span class="ident">end</span> <span class="op">=</span> <span class="self">self</span>.<span class="ident">num_bytes_remaining_in_current_chunk</span>;
<span class="kw">let</span> <span class="ident">num_bytes_written</span> <span class="op">=</span> <span class="self">self</span>.<span class="ident">inner</span>.<span class="ident">write</span>(<span class="kw-2">&amp;</span><span class="ident">buf</span>[..<span class="ident">end</span>])<span class="question-mark">?</span>;
<span class="self">self</span>.<span class="ident">num_bytes_remaining_in_current_chunk</span> <span class="op">-</span><span class="op">=</span> <span class="ident">num_bytes_written</span>;
<span class="ident">total_bytes_written</span> <span class="op">+</span><span class="op">=</span> <span class="ident">num_bytes_written</span>;
<span class="ident">buf</span> <span class="op">=</span> <span class="kw-2">&amp;</span><span class="ident">buf</span>[<span class="ident">num_bytes_written</span>..];
}
<span class="comment">// If there is a newline character, the line</span>
<span class="comment">// (including the newline character) will not fit in</span>
<span class="comment">// the current chunk, and at least one other line has</span>
<span class="comment">// been written to the current chunk, then signal to</span>
<span class="comment">// the next iteration that a new chunk needs to be</span>
<span class="comment">// created and continue to the next iteration of the</span>
<span class="comment">// loop to try writing the line there.</span>
<span class="prelude-val">Some</span>(<span class="kw">_</span>) =&gt; {
<span class="self">self</span>.<span class="ident">num_bytes_remaining_in_current_chunk</span> <span class="op">=</span> <span class="number">0</span>;
}
}
}
}
<span class="kw">fn</span> <span class="ident">flush</span>(<span class="kw-2">&amp;mut</span> <span class="self">self</span>) -&gt; <span class="ident">std::io::Result</span><span class="op">&lt;</span>()<span class="op">&gt;</span> {
<span class="self">self</span>.<span class="ident">inner</span>.<span class="ident">flush</span>()
}
}
<span class="doccomment">/// Split a file into a specific number of chunks by byte.</span>
<span class="doccomment">///</span>
<span class="doccomment">/// This function always creates one output file for each chunk, even</span>
<span class="doccomment">/// if there is an error reading or writing one of the chunks or if</span>
<span class="doccomment">/// the input file is truncated. However, if the `filter` option is</span>
<span class="doccomment">/// being used, then no files are created.</span>
<span class="doccomment">///</span>
<span class="doccomment">/// # Errors</span>
<span class="doccomment">///</span>
<span class="doccomment">/// This function returns an error if there is a problem reading from</span>
<span class="doccomment">/// `reader` or writing to one of the output files.</span>
<span class="kw">fn</span> <span class="ident">split_into_n_chunks_by_byte</span><span class="op">&lt;</span><span class="ident">R</span><span class="op">&gt;</span>(
<span class="ident">settings</span>: <span class="kw-2">&amp;</span><span class="ident">Settings</span>,
<span class="ident">reader</span>: <span class="kw-2">&amp;mut</span> <span class="ident">R</span>,
<span class="ident">num_chunks</span>: <span class="ident">u64</span>,
) -&gt; <span class="ident">UResult</span><span class="op">&lt;</span>()<span class="op">&gt;</span>
<span class="kw">where</span>
<span class="ident">R</span>: <span class="ident">Read</span>,
{
<span class="comment">// Get the size of the input file in bytes and compute the number</span>
<span class="comment">// of bytes per chunk.</span>
<span class="comment">//</span>
<span class="comment">// If the requested number of chunks exceeds the number of bytes</span>
<span class="comment">// in the file *and* the `elide_empty_files` parameter is enabled,</span>
<span class="comment">// then behave as if the number of chunks was set to the number of</span>
<span class="comment">// bytes in the file. This ensures that we don&#39;t write empty</span>
<span class="comment">// files. Otherwise, just write the `num_chunks - num_bytes` empty</span>
<span class="comment">// files.</span>
<span class="kw">let</span> <span class="ident">metadata</span> <span class="op">=</span> <span class="ident">metadata</span>(<span class="kw-2">&amp;</span><span class="ident">settings</span>.<span class="ident">input</span>).<span class="ident">map_err</span>(<span class="op">|</span><span class="kw">_</span><span class="op">|</span> {
<span class="ident">USimpleError::new</span>(<span class="number">1</span>, <span class="macro">format!</span>(<span class="string">&quot;{}: cannot determine file size&quot;</span>, <span class="ident">settings</span>.<span class="ident">input</span>))
})<span class="question-mark">?</span>;
<span class="kw">let</span> <span class="ident">num_bytes</span> <span class="op">=</span> <span class="ident">metadata</span>.<span class="ident">len</span>();
<span class="kw">let</span> <span class="ident">will_have_empty_files</span> <span class="op">=</span> <span class="ident">settings</span>.<span class="ident">elide_empty_files</span> <span class="op">&amp;&amp;</span> <span class="ident">num_chunks</span> <span class="op">&gt;</span> <span class="ident">num_bytes</span>;
<span class="kw">let</span> (<span class="ident">num_chunks</span>, <span class="ident">chunk_size</span>) <span class="op">=</span> <span class="kw">if</span> <span class="ident">will_have_empty_files</span> {
<span class="kw">let</span> <span class="ident">num_chunks</span> <span class="op">=</span> <span class="ident">num_bytes</span>;
<span class="kw">let</span> <span class="ident">chunk_size</span> <span class="op">=</span> <span class="number">1</span>;
(<span class="ident">num_chunks</span>, <span class="ident">chunk_size</span>)
} <span class="kw">else</span> {
<span class="kw">let</span> <span class="ident">chunk_size</span> <span class="op">=</span> (<span class="ident">num_bytes</span> <span class="op">/</span> (<span class="ident">num_chunks</span>)).<span class="ident">max</span>(<span class="number">1</span>);
(<span class="ident">num_chunks</span>, <span class="ident">chunk_size</span>)
};
<span class="comment">// If we would have written zero chunks of output, then terminate</span>
<span class="comment">// immediately. This happens on `split -e -n 3 /dev/null`, for</span>
<span class="comment">// example.</span>
<span class="kw">if</span> <span class="ident">num_chunks</span> <span class="op">==</span> <span class="number">0</span> {
<span class="kw">return</span> <span class="prelude-val">Ok</span>(());
}
<span class="kw">let</span> <span class="ident">num_chunks</span>: <span class="ident">usize</span> <span class="op">=</span> <span class="ident">num_chunks</span>
.<span class="ident">try_into</span>()
.<span class="ident">map_err</span>(<span class="op">|</span><span class="kw">_</span><span class="op">|</span> <span class="ident">USimpleError::new</span>(<span class="number">1</span>, <span class="string">&quot;Number of chunks too big&quot;</span>))<span class="question-mark">?</span>;
<span class="comment">// This object is responsible for creating the filename for each chunk.</span>
<span class="kw">let</span> <span class="kw-2">mut</span> <span class="ident">filename_iterator</span> <span class="op">=</span> <span class="ident">FilenameIterator::new</span>(
<span class="kw-2">&amp;</span><span class="ident">settings</span>.<span class="ident">prefix</span>,
<span class="kw-2">&amp;</span><span class="ident">settings</span>.<span class="ident">additional_suffix</span>,
<span class="ident">settings</span>.<span class="ident">suffix_length</span>,
<span class="ident">settings</span>.<span class="ident">suffix_type</span>,
<span class="ident">settings</span>.<span class="ident">suffix_start</span>,
)<span class="question-mark">?</span>;
<span class="comment">// Create one writer for each chunk. This will create each</span>
<span class="comment">// of the underlying files (if not in `--filter` mode).</span>
<span class="kw">let</span> <span class="kw-2">mut</span> <span class="ident">writers</span> <span class="op">=</span> <span class="macro">vec!</span>[];
<span class="kw">for</span> <span class="kw">_</span> <span class="kw">in</span> <span class="number">0</span>..<span class="ident">num_chunks</span> {
<span class="kw">let</span> <span class="ident">filename</span> <span class="op">=</span> <span class="ident">filename_iterator</span>
.<span class="ident">next</span>()
.<span class="ident">ok_or_else</span>(<span class="op">|</span><span class="op">|</span> <span class="ident">USimpleError::new</span>(<span class="number">1</span>, <span class="string">&quot;output file suffixes exhausted&quot;</span>))<span class="question-mark">?</span>;
<span class="kw">let</span> <span class="ident">writer</span> <span class="op">=</span> <span class="ident">settings</span>.<span class="ident">instantiate_current_writer</span>(<span class="ident">filename</span>.<span class="ident">as_str</span>())<span class="question-mark">?</span>;
<span class="ident">writers</span>.<span class="ident">push</span>(<span class="ident">writer</span>);
}
<span class="comment">// Capture the result of the `std::io::copy()` calls to check for</span>
<span class="comment">// `BrokenPipe`.</span>
<span class="kw">let</span> <span class="ident">result</span>: <span class="ident">std::io::Result</span><span class="op">&lt;</span>()<span class="op">&gt;</span> <span class="op">=</span> {
<span class="comment">// Write `chunk_size` bytes from the reader into each writer</span>
<span class="comment">// except the last.</span>
<span class="comment">//</span>
<span class="comment">// The last writer gets all remaining bytes so that if the number</span>
<span class="comment">// of bytes in the input file was not evenly divisible by</span>
<span class="comment">// `num_chunks`, we don&#39;t leave any bytes behind.</span>
<span class="kw">for</span> <span class="ident">writer</span> <span class="kw">in</span> <span class="ident">writers</span>.<span class="ident">iter_mut</span>().<span class="ident">take</span>(<span class="ident">num_chunks</span> <span class="op">-</span> <span class="number">1</span>) {
<span class="ident">io::copy</span>(<span class="kw-2">&amp;mut</span> <span class="ident">reader</span>.<span class="ident">by_ref</span>().<span class="ident">take</span>(<span class="ident">chunk_size</span>), <span class="ident">writer</span>)<span class="question-mark">?</span>;
}
<span class="comment">// Write all the remaining bytes to the last chunk.</span>
<span class="kw">let</span> <span class="ident">i</span> <span class="op">=</span> <span class="ident">num_chunks</span> <span class="op">-</span> <span class="number">1</span>;
<span class="kw">let</span> <span class="ident">last_chunk_size</span> <span class="op">=</span> <span class="ident">num_bytes</span> <span class="op">-</span> (<span class="ident">chunk_size</span> <span class="op">*</span> (<span class="ident">num_chunks</span> <span class="kw">as</span> <span class="ident">u64</span> <span class="op">-</span> <span class="number">1</span>));
<span class="ident">io::copy</span>(<span class="kw-2">&amp;mut</span> <span class="ident">reader</span>.<span class="ident">by_ref</span>().<span class="ident">take</span>(<span class="ident">last_chunk_size</span>), <span class="kw-2">&amp;mut</span> <span class="ident">writers</span>[<span class="ident">i</span>])<span class="question-mark">?</span>;
<span class="prelude-val">Ok</span>(())
};
<span class="kw">match</span> <span class="ident">result</span> {
<span class="prelude-val">Ok</span>(<span class="kw">_</span>) =&gt; <span class="prelude-val">Ok</span>(()),
<span class="prelude-val">Err</span>(<span class="ident">e</span>) <span class="kw">if</span> <span class="ident">e</span>.<span class="ident">kind</span>() <span class="op">==</span> <span class="ident">ErrorKind::BrokenPipe</span> =&gt; <span class="prelude-val">Ok</span>(()),
<span class="prelude-val">Err</span>(<span class="ident">e</span>) =&gt; <span class="prelude-val">Err</span>(<span class="macro">uio_error!</span>(<span class="ident">e</span>, <span class="string">&quot;input/output error&quot;</span>)),
}
}
<span class="doccomment">/// Split a file into a specific number of chunks by line.</span>
<span class="doccomment">///</span>
<span class="doccomment">/// This function always creates one output file for each chunk, even</span>
<span class="doccomment">/// if there is an error reading or writing one of the chunks or if</span>
<span class="doccomment">/// the input file is truncated. However, if the `filter` option is</span>
<span class="doccomment">/// being used, then no files are created.</span>
<span class="doccomment">///</span>
<span class="doccomment">/// # Errors</span>
<span class="doccomment">///</span>
<span class="doccomment">/// This function returns an error if there is a problem reading from</span>
<span class="doccomment">/// `reader` or writing to one of the output files.</span>
<span class="doccomment">///</span>
<span class="doccomment">/// # See also</span>
<span class="doccomment">///</span>
<span class="doccomment">/// * [`kth_chunk_by_line`], which splits its input in the same way,</span>
<span class="doccomment">/// but writes only one specified chunk to stdout.</span>
<span class="kw">fn</span> <span class="ident">split_into_n_chunks_by_line</span><span class="op">&lt;</span><span class="ident">R</span><span class="op">&gt;</span>(
<span class="ident">settings</span>: <span class="kw-2">&amp;</span><span class="ident">Settings</span>,
<span class="ident">reader</span>: <span class="kw-2">&amp;mut</span> <span class="ident">R</span>,
<span class="ident">num_chunks</span>: <span class="ident">u64</span>,
) -&gt; <span class="ident">UResult</span><span class="op">&lt;</span>()<span class="op">&gt;</span>
<span class="kw">where</span>
<span class="ident">R</span>: <span class="ident">BufRead</span>,
{
<span class="comment">// Get the size of the input file in bytes and compute the number</span>
<span class="comment">// of bytes per chunk.</span>
<span class="kw">let</span> <span class="ident">metadata</span> <span class="op">=</span> <span class="ident">metadata</span>(<span class="kw-2">&amp;</span><span class="ident">settings</span>.<span class="ident">input</span>).<span class="ident">unwrap</span>();
<span class="kw">let</span> <span class="ident">num_bytes</span> <span class="op">=</span> <span class="ident">metadata</span>.<span class="ident">len</span>();
<span class="kw">let</span> <span class="ident">chunk_size</span> <span class="op">=</span> (<span class="ident">num_bytes</span> <span class="op">/</span> (<span class="ident">num_chunks</span> <span class="kw">as</span> <span class="ident">u64</span>)) <span class="kw">as</span> <span class="ident">usize</span>;
<span class="comment">// This object is responsible for creating the filename for each chunk.</span>
<span class="kw">let</span> <span class="kw-2">mut</span> <span class="ident">filename_iterator</span> <span class="op">=</span> <span class="ident">FilenameIterator::new</span>(
<span class="kw-2">&amp;</span><span class="ident">settings</span>.<span class="ident">prefix</span>,
<span class="kw-2">&amp;</span><span class="ident">settings</span>.<span class="ident">additional_suffix</span>,
<span class="ident">settings</span>.<span class="ident">suffix_length</span>,
<span class="ident">settings</span>.<span class="ident">suffix_type</span>,
<span class="ident">settings</span>.<span class="ident">suffix_start</span>,
)<span class="question-mark">?</span>;
<span class="comment">// Create one writer for each chunk. This will create each</span>
<span class="comment">// of the underlying files (if not in `--filter` mode).</span>
<span class="kw">let</span> <span class="kw-2">mut</span> <span class="ident">writers</span> <span class="op">=</span> <span class="macro">vec!</span>[];
<span class="kw">for</span> <span class="kw">_</span> <span class="kw">in</span> <span class="number">0</span>..<span class="ident">num_chunks</span> {
<span class="kw">let</span> <span class="ident">filename</span> <span class="op">=</span> <span class="ident">filename_iterator</span>
.<span class="ident">next</span>()
.<span class="ident">ok_or_else</span>(<span class="op">|</span><span class="op">|</span> <span class="ident">USimpleError::new</span>(<span class="number">1</span>, <span class="string">&quot;output file suffixes exhausted&quot;</span>))<span class="question-mark">?</span>;
<span class="kw">let</span> <span class="ident">writer</span> <span class="op">=</span> <span class="ident">settings</span>.<span class="ident">instantiate_current_writer</span>(<span class="ident">filename</span>.<span class="ident">as_str</span>())<span class="question-mark">?</span>;
<span class="ident">writers</span>.<span class="ident">push</span>(<span class="ident">writer</span>);
}
<span class="kw">let</span> <span class="kw-2">mut</span> <span class="ident">num_bytes_remaining_in_current_chunk</span> <span class="op">=</span> <span class="ident">chunk_size</span>;
<span class="kw">let</span> <span class="kw-2">mut</span> <span class="ident">i</span> <span class="op">=</span> <span class="number">0</span>;
<span class="kw">for</span> <span class="ident">line_result</span> <span class="kw">in</span> <span class="ident">reader</span>.<span class="ident">lines</span>() {
<span class="kw">let</span> <span class="ident">line</span> <span class="op">=</span> <span class="ident">line_result</span>.<span class="ident">unwrap</span>();
<span class="kw">let</span> <span class="ident">maybe_writer</span> <span class="op">=</span> <span class="ident">writers</span>.<span class="ident">get_mut</span>(<span class="ident">i</span>);
<span class="kw">let</span> <span class="ident">writer</span> <span class="op">=</span> <span class="ident">maybe_writer</span>.<span class="ident">unwrap</span>();
<span class="kw">let</span> <span class="ident">bytes</span> <span class="op">=</span> <span class="ident">line</span>.<span class="ident">as_bytes</span>();
<span class="ident">writer</span>.<span class="ident">write_all</span>(<span class="ident">bytes</span>)<span class="question-mark">?</span>;
<span class="ident">writer</span>.<span class="ident">write_all</span>(<span class="string">b&quot;\n&quot;</span>)<span class="question-mark">?</span>;
<span class="comment">// Add one byte for the newline character.</span>
<span class="kw">let</span> <span class="ident">num_bytes</span> <span class="op">=</span> <span class="ident">bytes</span>.<span class="ident">len</span>() <span class="op">+</span> <span class="number">1</span>;
<span class="kw">if</span> <span class="ident">num_bytes</span> <span class="op">&gt;</span> <span class="ident">num_bytes_remaining_in_current_chunk</span> {
<span class="ident">num_bytes_remaining_in_current_chunk</span> <span class="op">=</span> <span class="ident">chunk_size</span>;
<span class="ident">i</span> <span class="op">+</span><span class="op">=</span> <span class="number">1</span>;
} <span class="kw">else</span> {
<span class="ident">num_bytes_remaining_in_current_chunk</span> <span class="op">-</span><span class="op">=</span> <span class="ident">num_bytes</span>;
}
}
<span class="prelude-val">Ok</span>(())
}
<span class="doccomment">/// Print the k-th chunk of a file, splitting by line.</span>
<span class="doccomment">///</span>
<span class="doccomment">/// This function is like [`split_into_n_chunks_by_line`], but instead</span>
<span class="doccomment">/// of writing each chunk to its own file, it only writes to stdout</span>
<span class="doccomment">/// the contents of the chunk identified by `chunk_number`.</span>
<span class="doccomment">///</span>
<span class="doccomment">/// # Errors</span>
<span class="doccomment">///</span>
<span class="doccomment">/// This function returns an error if there is a problem reading from</span>
<span class="doccomment">/// `reader` or writing to one of the output files.</span>
<span class="doccomment">///</span>
<span class="doccomment">/// # See also</span>
<span class="doccomment">///</span>
<span class="doccomment">/// * [`split_into_n_chunks_by_line`], which splits its input in the</span>
<span class="doccomment">/// same way, but writes each chunk to its own file.</span>
<span class="kw">fn</span> <span class="ident">kth_chunk_by_line</span><span class="op">&lt;</span><span class="ident">R</span><span class="op">&gt;</span>(
<span class="ident">settings</span>: <span class="kw-2">&amp;</span><span class="ident">Settings</span>,
<span class="ident">reader</span>: <span class="kw-2">&amp;mut</span> <span class="ident">R</span>,
<span class="ident">chunk_number</span>: <span class="ident">u64</span>,
<span class="ident">num_chunks</span>: <span class="ident">u64</span>,
) -&gt; <span class="ident">UResult</span><span class="op">&lt;</span>()<span class="op">&gt;</span>
<span class="kw">where</span>
<span class="ident">R</span>: <span class="ident">BufRead</span>,
{
<span class="comment">// Get the size of the input file in bytes and compute the number</span>
<span class="comment">// of bytes per chunk.</span>
<span class="kw">let</span> <span class="ident">metadata</span> <span class="op">=</span> <span class="ident">metadata</span>(<span class="kw-2">&amp;</span><span class="ident">settings</span>.<span class="ident">input</span>).<span class="ident">unwrap</span>();
<span class="kw">let</span> <span class="ident">num_bytes</span> <span class="op">=</span> <span class="ident">metadata</span>.<span class="ident">len</span>();
<span class="kw">let</span> <span class="ident">chunk_size</span> <span class="op">=</span> (<span class="ident">num_bytes</span> <span class="op">/</span> (<span class="ident">num_chunks</span> <span class="kw">as</span> <span class="ident">u64</span>)) <span class="kw">as</span> <span class="ident">usize</span>;
<span class="comment">// Write to stdout instead of to a file.</span>
<span class="kw">let</span> <span class="ident">stdout</span> <span class="op">=</span> <span class="ident">std::io::stdout</span>();
<span class="kw">let</span> <span class="kw-2">mut</span> <span class="ident">writer</span> <span class="op">=</span> <span class="ident">stdout</span>.<span class="ident">lock</span>();
<span class="kw">let</span> <span class="kw-2">mut</span> <span class="ident">num_bytes_remaining_in_current_chunk</span> <span class="op">=</span> <span class="ident">chunk_size</span>;
<span class="kw">let</span> <span class="kw-2">mut</span> <span class="ident">i</span> <span class="op">=</span> <span class="number">0</span>;
<span class="kw">for</span> <span class="ident">line_result</span> <span class="kw">in</span> <span class="ident">reader</span>.<span class="ident">lines</span>() {
<span class="kw">let</span> <span class="ident">line</span> <span class="op">=</span> <span class="ident">line_result</span><span class="question-mark">?</span>;
<span class="kw">let</span> <span class="ident">bytes</span> <span class="op">=</span> <span class="ident">line</span>.<span class="ident">as_bytes</span>();
<span class="kw">if</span> <span class="ident">i</span> <span class="op">==</span> <span class="ident">chunk_number</span> {
<span class="ident">writer</span>.<span class="ident">write_all</span>(<span class="ident">bytes</span>)<span class="question-mark">?</span>;
<span class="ident">writer</span>.<span class="ident">write_all</span>(<span class="string">b&quot;\n&quot;</span>)<span class="question-mark">?</span>;
}
<span class="comment">// Add one byte for the newline character.</span>
<span class="kw">let</span> <span class="ident">num_bytes</span> <span class="op">=</span> <span class="ident">bytes</span>.<span class="ident">len</span>() <span class="op">+</span> <span class="number">1</span>;
<span class="kw">if</span> <span class="ident">num_bytes</span> <span class="op">&gt;</span><span class="op">=</span> <span class="ident">num_bytes_remaining_in_current_chunk</span> {
<span class="ident">num_bytes_remaining_in_current_chunk</span> <span class="op">=</span> <span class="ident">chunk_size</span>;
<span class="ident">i</span> <span class="op">+</span><span class="op">=</span> <span class="number">1</span>;
} <span class="kw">else</span> {
<span class="ident">num_bytes_remaining_in_current_chunk</span> <span class="op">-</span><span class="op">=</span> <span class="ident">num_bytes</span>;
}
<span class="kw">if</span> <span class="ident">i</span> <span class="op">&gt;</span> <span class="ident">chunk_number</span> {
<span class="kw">break</span>;
}
}
<span class="prelude-val">Ok</span>(())
}
<span class="kw">fn</span> <span class="ident">split</span>(<span class="ident">settings</span>: <span class="kw-2">&amp;</span><span class="ident">Settings</span>) -&gt; <span class="ident">UResult</span><span class="op">&lt;</span>()<span class="op">&gt;</span> {
<span class="kw">let</span> <span class="kw-2">mut</span> <span class="ident">reader</span> <span class="op">=</span> <span class="ident">BufReader::new</span>(<span class="kw">if</span> <span class="ident">settings</span>.<span class="ident">input</span> <span class="op">==</span> <span class="string">&quot;-&quot;</span> {
<span class="ident">Box::new</span>(<span class="ident">stdin</span>()) <span class="kw">as</span> <span class="ident">Box</span><span class="op">&lt;</span><span class="kw">dyn</span> <span class="ident">Read</span><span class="op">&gt;</span>
} <span class="kw">else</span> {
<span class="kw">let</span> <span class="ident">r</span> <span class="op">=</span> <span class="ident">File::open</span>(<span class="ident">Path::new</span>(<span class="kw-2">&amp;</span><span class="ident">settings</span>.<span class="ident">input</span>)).<span class="ident">map_err_context</span>(<span class="op">|</span><span class="op">|</span> {
<span class="macro">format!</span>(
<span class="string">&quot;cannot open {} for reading: No such file or directory&quot;</span>,
<span class="ident">settings</span>.<span class="ident">input</span>.<span class="ident">quote</span>()
)
})<span class="question-mark">?</span>;
<span class="ident">Box::new</span>(<span class="ident">r</span>) <span class="kw">as</span> <span class="ident">Box</span><span class="op">&lt;</span><span class="kw">dyn</span> <span class="ident">Read</span><span class="op">&gt;</span>
});
<span class="kw">match</span> <span class="ident">settings</span>.<span class="ident">strategy</span> {
<span class="ident">Strategy::Number</span>(<span class="ident">NumberType::Bytes</span>(<span class="ident">num_chunks</span>)) =&gt; {
<span class="ident">split_into_n_chunks_by_byte</span>(<span class="ident">settings</span>, <span class="kw-2">&amp;mut</span> <span class="ident">reader</span>, <span class="ident">num_chunks</span>)
}
<span class="ident">Strategy::Number</span>(<span class="ident">NumberType::Lines</span>(<span class="ident">num_chunks</span>)) =&gt; {
<span class="ident">split_into_n_chunks_by_line</span>(<span class="ident">settings</span>, <span class="kw-2">&amp;mut</span> <span class="ident">reader</span>, <span class="ident">num_chunks</span>)
}
<span class="ident">Strategy::Number</span>(<span class="ident">NumberType::KthLines</span>(<span class="ident">chunk_number</span>, <span class="ident">num_chunks</span>)) =&gt; {
<span class="comment">// The chunk number is given as a 1-indexed number, but it</span>
<span class="comment">// is a little easier to deal with a 0-indexed number.</span>
<span class="kw">let</span> <span class="ident">chunk_number</span> <span class="op">=</span> <span class="ident">chunk_number</span> <span class="op">-</span> <span class="number">1</span>;
<span class="ident">kth_chunk_by_line</span>(<span class="ident">settings</span>, <span class="kw-2">&amp;mut</span> <span class="ident">reader</span>, <span class="ident">chunk_number</span>, <span class="ident">num_chunks</span>)
}
<span class="ident">Strategy::Number</span>(<span class="kw">_</span>) =&gt; <span class="prelude-val">Err</span>(<span class="ident">USimpleError::new</span>(<span class="number">1</span>, <span class="string">&quot;-n mode not yet fully implemented&quot;</span>)),
<span class="ident">Strategy::Lines</span>(<span class="ident">chunk_size</span>) =&gt; {
<span class="kw">let</span> <span class="kw-2">mut</span> <span class="ident">writer</span> <span class="op">=</span> <span class="ident">LineChunkWriter::new</span>(<span class="ident">chunk_size</span>, <span class="ident">settings</span>)<span class="question-mark">?</span>;
<span class="kw">match</span> <span class="ident">std::io::copy</span>(<span class="kw-2">&amp;mut</span> <span class="ident">reader</span>, <span class="kw-2">&amp;mut</span> <span class="ident">writer</span>) {
<span class="prelude-val">Ok</span>(<span class="kw">_</span>) =&gt; <span class="prelude-val">Ok</span>(()),
<span class="prelude-val">Err</span>(<span class="ident">e</span>) =&gt; <span class="kw">match</span> <span class="ident">e</span>.<span class="ident">kind</span>() {
<span class="comment">// TODO Since the writer object controls the creation of</span>
<span class="comment">// new files, we need to rely on the `std::io::Result`</span>
<span class="comment">// returned by its `write()` method to communicate any</span>
<span class="comment">// errors to this calling scope. If a new file cannot be</span>
<span class="comment">// created because we have exceeded the number of</span>
<span class="comment">// allowable filenames, we use `ErrorKind::Other` to</span>
<span class="comment">// indicate that. A special error message needs to be</span>
<span class="comment">// printed in that case.</span>
<span class="ident">ErrorKind::Other</span> =&gt; <span class="prelude-val">Err</span>(<span class="ident">USimpleError::new</span>(<span class="number">1</span>, <span class="macro">format!</span>(<span class="string">&quot;{}&quot;</span>, <span class="ident">e</span>))),
<span class="ident">ErrorKind::BrokenPipe</span> =&gt; <span class="prelude-val">Ok</span>(()),
<span class="kw">_</span> =&gt; <span class="prelude-val">Err</span>(<span class="macro">uio_error!</span>(<span class="ident">e</span>, <span class="string">&quot;input/output error&quot;</span>)),
},
}
}
<span class="ident">Strategy::Bytes</span>(<span class="ident">chunk_size</span>) =&gt; {
<span class="kw">let</span> <span class="kw-2">mut</span> <span class="ident">writer</span> <span class="op">=</span> <span class="ident">ByteChunkWriter::new</span>(<span class="ident">chunk_size</span>, <span class="ident">settings</span>)<span class="question-mark">?</span>;
<span class="kw">match</span> <span class="ident">std::io::copy</span>(<span class="kw-2">&amp;mut</span> <span class="ident">reader</span>, <span class="kw-2">&amp;mut</span> <span class="ident">writer</span>) {
<span class="prelude-val">Ok</span>(<span class="kw">_</span>) =&gt; <span class="prelude-val">Ok</span>(()),
<span class="prelude-val">Err</span>(<span class="ident">e</span>) =&gt; <span class="kw">match</span> <span class="ident">e</span>.<span class="ident">kind</span>() {
<span class="comment">// TODO Since the writer object controls the creation of</span>
<span class="comment">// new files, we need to rely on the `std::io::Result`</span>
<span class="comment">// returned by its `write()` method to communicate any</span>
<span class="comment">// errors to this calling scope. If a new file cannot be</span>
<span class="comment">// created because we have exceeded the number of</span>
<span class="comment">// allowable filenames, we use `ErrorKind::Other` to</span>
<span class="comment">// indicate that. A special error message needs to be</span>
<span class="comment">// printed in that case.</span>
<span class="ident">ErrorKind::Other</span> =&gt; <span class="prelude-val">Err</span>(<span class="ident">USimpleError::new</span>(<span class="number">1</span>, <span class="macro">format!</span>(<span class="string">&quot;{}&quot;</span>, <span class="ident">e</span>))),
<span class="ident">ErrorKind::BrokenPipe</span> =&gt; <span class="prelude-val">Ok</span>(()),
<span class="kw">_</span> =&gt; <span class="prelude-val">Err</span>(<span class="macro">uio_error!</span>(<span class="ident">e</span>, <span class="string">&quot;input/output error&quot;</span>)),
},
}
}
<span class="ident">Strategy::LineBytes</span>(<span class="ident">chunk_size</span>) =&gt; {
<span class="kw">let</span> <span class="kw-2">mut</span> <span class="ident">writer</span> <span class="op">=</span> <span class="ident">LineBytesChunkWriter::new</span>(<span class="ident">chunk_size</span>, <span class="ident">settings</span>)<span class="question-mark">?</span>;
<span class="kw">match</span> <span class="ident">std::io::copy</span>(<span class="kw-2">&amp;mut</span> <span class="ident">reader</span>, <span class="kw-2">&amp;mut</span> <span class="ident">writer</span>) {
<span class="prelude-val">Ok</span>(<span class="kw">_</span>) =&gt; <span class="prelude-val">Ok</span>(()),
<span class="prelude-val">Err</span>(<span class="ident">e</span>) =&gt; <span class="kw">match</span> <span class="ident">e</span>.<span class="ident">kind</span>() {
<span class="comment">// TODO Since the writer object controls the creation of</span>
<span class="comment">// new files, we need to rely on the `std::io::Result`</span>
<span class="comment">// returned by its `write()` method to communicate any</span>
<span class="comment">// errors to this calling scope. If a new file cannot be</span>
<span class="comment">// created because we have exceeded the number of</span>
<span class="comment">// allowable filenames, we use `ErrorKind::Other` to</span>
<span class="comment">// indicate that. A special error message needs to be</span>
<span class="comment">// printed in that case.</span>
<span class="ident">ErrorKind::Other</span> =&gt; <span class="prelude-val">Err</span>(<span class="ident">USimpleError::new</span>(<span class="number">1</span>, <span class="macro">format!</span>(<span class="string">&quot;{}&quot;</span>, <span class="ident">e</span>))),
<span class="ident">ErrorKind::BrokenPipe</span> =&gt; <span class="prelude-val">Ok</span>(()),
<span class="kw">_</span> =&gt; <span class="prelude-val">Err</span>(<span class="macro">uio_error!</span>(<span class="ident">e</span>, <span class="string">&quot;input/output error&quot;</span>)),
},
}
}
}
}
<span class="attribute">#[<span class="ident">cfg</span>(<span class="ident">test</span>)]</span>
<span class="kw">mod</span> <span class="ident">tests</span> {
<span class="kw">use</span> <span class="ident"><span class="kw">crate</span>::NumberType</span>;
<span class="kw">use</span> <span class="ident"><span class="kw">crate</span>::NumberTypeError</span>;
<span class="attribute">#[<span class="ident">test</span>]</span>
<span class="kw">fn</span> <span class="ident">test_number_type_from</span>() {
<span class="macro">assert_eq!</span>(<span class="ident">NumberType::from</span>(<span class="string">&quot;123&quot;</span>).<span class="ident">unwrap</span>(), <span class="ident">NumberType::Bytes</span>(<span class="number">123</span>));
<span class="macro">assert_eq!</span>(<span class="ident">NumberType::from</span>(<span class="string">&quot;l/123&quot;</span>).<span class="ident">unwrap</span>(), <span class="ident">NumberType::Lines</span>(<span class="number">123</span>));
<span class="macro">assert_eq!</span>(
<span class="ident">NumberType::from</span>(<span class="string">&quot;l/123/456&quot;</span>).<span class="ident">unwrap</span>(),
<span class="ident">NumberType::KthLines</span>(<span class="number">123</span>, <span class="number">456</span>)
);
<span class="macro">assert_eq!</span>(
<span class="ident">NumberType::from</span>(<span class="string">&quot;r/123&quot;</span>).<span class="ident">unwrap</span>(),
<span class="ident">NumberType::RoundRobin</span>(<span class="number">123</span>)
);
<span class="macro">assert_eq!</span>(
<span class="ident">NumberType::from</span>(<span class="string">&quot;r/123/456&quot;</span>).<span class="ident">unwrap</span>(),
<span class="ident">NumberType::KthRoundRobin</span>(<span class="number">123</span>, <span class="number">456</span>)
);
}
<span class="attribute">#[<span class="ident">test</span>]</span>
<span class="kw">fn</span> <span class="ident">test_number_type_from_error</span>() {
<span class="macro">assert_eq!</span>(
<span class="ident">NumberType::from</span>(<span class="string">&quot;xyz&quot;</span>).<span class="ident">unwrap_err</span>(),
<span class="ident">NumberTypeError::NumberOfChunks</span>(<span class="string">&quot;xyz&quot;</span>.<span class="ident">to_string</span>())
);
<span class="macro">assert_eq!</span>(
<span class="ident">NumberType::from</span>(<span class="string">&quot;l/xyz&quot;</span>).<span class="ident">unwrap_err</span>(),
<span class="ident">NumberTypeError::NumberOfChunks</span>(<span class="string">&quot;xyz&quot;</span>.<span class="ident">to_string</span>())
);
<span class="macro">assert_eq!</span>(
<span class="ident">NumberType::from</span>(<span class="string">&quot;l/123/xyz&quot;</span>).<span class="ident">unwrap_err</span>(),
<span class="ident">NumberTypeError::NumberOfChunks</span>(<span class="string">&quot;xyz&quot;</span>.<span class="ident">to_string</span>())
);
<span class="macro">assert_eq!</span>(
<span class="ident">NumberType::from</span>(<span class="string">&quot;l/abc/456&quot;</span>).<span class="ident">unwrap_err</span>(),
<span class="ident">NumberTypeError::ChunkNumber</span>(<span class="string">&quot;abc&quot;</span>.<span class="ident">to_string</span>())
);
<span class="comment">// In GNU split, the number of chunks get precedence:</span>
<span class="comment">//</span>
<span class="comment">// $ split -n l/abc/xyz</span>
<span class="comment">// split: invalid number of chunks: xyz</span>
<span class="comment">//</span>
<span class="macro">assert_eq!</span>(
<span class="ident">NumberType::from</span>(<span class="string">&quot;l/abc/xyz&quot;</span>).<span class="ident">unwrap_err</span>(),
<span class="ident">NumberTypeError::NumberOfChunks</span>(<span class="string">&quot;xyz&quot;</span>.<span class="ident">to_string</span>())
);
<span class="macro">assert_eq!</span>(
<span class="ident">NumberType::from</span>(<span class="string">&quot;r/xyz&quot;</span>).<span class="ident">unwrap_err</span>(),
<span class="ident">NumberTypeError::NumberOfChunks</span>(<span class="string">&quot;xyz&quot;</span>.<span class="ident">to_string</span>())
);
<span class="macro">assert_eq!</span>(
<span class="ident">NumberType::from</span>(<span class="string">&quot;r/123/xyz&quot;</span>).<span class="ident">unwrap_err</span>(),
<span class="ident">NumberTypeError::NumberOfChunks</span>(<span class="string">&quot;xyz&quot;</span>.<span class="ident">to_string</span>())
);
<span class="macro">assert_eq!</span>(
<span class="ident">NumberType::from</span>(<span class="string">&quot;r/abc/456&quot;</span>).<span class="ident">unwrap_err</span>(),
<span class="ident">NumberTypeError::ChunkNumber</span>(<span class="string">&quot;abc&quot;</span>.<span class="ident">to_string</span>())
);
<span class="comment">// In GNU split, the number of chunks get precedence:</span>
<span class="comment">//</span>
<span class="comment">// $ split -n r/abc/xyz</span>
<span class="comment">// split: invalid number of chunks: xyz</span>
<span class="comment">//</span>
<span class="macro">assert_eq!</span>(
<span class="ident">NumberType::from</span>(<span class="string">&quot;r/abc/xyz&quot;</span>).<span class="ident">unwrap_err</span>(),
<span class="ident">NumberTypeError::NumberOfChunks</span>(<span class="string">&quot;xyz&quot;</span>.<span class="ident">to_string</span>())
);
}
<span class="attribute">#[<span class="ident">test</span>]</span>
<span class="kw">fn</span> <span class="ident">test_number_type_num_chunks</span>() {
<span class="macro">assert_eq!</span>(<span class="ident">NumberType::from</span>(<span class="string">&quot;123&quot;</span>).<span class="ident">unwrap</span>().<span class="ident">num_chunks</span>(), <span class="number">123</span>);
<span class="macro">assert_eq!</span>(<span class="ident">NumberType::from</span>(<span class="string">&quot;l/123&quot;</span>).<span class="ident">unwrap</span>().<span class="ident">num_chunks</span>(), <span class="number">123</span>);
<span class="macro">assert_eq!</span>(<span class="ident">NumberType::from</span>(<span class="string">&quot;l/123/456&quot;</span>).<span class="ident">unwrap</span>().<span class="ident">num_chunks</span>(), <span class="number">456</span>);
<span class="macro">assert_eq!</span>(<span class="ident">NumberType::from</span>(<span class="string">&quot;r/123&quot;</span>).<span class="ident">unwrap</span>().<span class="ident">num_chunks</span>(), <span class="number">123</span>);
<span class="macro">assert_eq!</span>(<span class="ident">NumberType::from</span>(<span class="string">&quot;r/123/456&quot;</span>).<span class="ident">unwrap</span>().<span class="ident">num_chunks</span>(), <span class="number">456</span>);
}
}
</code></pre></div>
</section></div></main><div id="rustdoc-vars" data-root-path="../../" data-current-crate="uu_split" data-themes="ayu,dark,light" data-resource-suffix="" data-rustdoc-version="1.64.0 (a55dd71d5 2022-09-19)" ></div></body></html>