Files
uutils.github.io/dev/src/uu_split/split.rs.html
T
2022-02-13 02:36:51 +00:00

1406 lines
92 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&#x2F;uu&#x2F;split&#x2F;src&#x2F;split.rs`."><meta name="keywords" content="rust, rustlang, rust-lang"><title>split.rs - source</title><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="../../light.css" id="themeStyle"><link rel="stylesheet" type="text/css" href="../../dark.css" disabled ><link rel="stylesheet" type="text/css" href="../../ayu.css" disabled ><script id="default-settings" ></script><script src="../../storage.js"></script><script src="../../crates.js"></script><script defer src="../../main.js"></script><script defer src="../../source-script.js"></script><script defer src="../../source-files.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"><style type="text/css">#crate-search{background-image:url("../../down-arrow.svg");}</style></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="sidebar"><div class="sidebar-menu" role="button">&#9776;</div><a href='../../uu_split/index.html'><div class='logo-container rust-logo'><img src='../../rust-logo.png' alt='logo'></div></a></nav><div class="theme-picker"><button id="theme-picker" aria-label="Pick another theme!" aria-haspopup="menu" title="themes"><img width="18" height="18" alt="Pick another theme!" src="../../brush.svg"></button><div id="theme-choices" role="menu"></div></div><nav class="sub"><form class="search-form"><div class="search-container"><div><select id="crate-search"><option value="All crates">All crates</option></select><input class="search-input" name="search" autocomplete="off" spellcheck="false" placeholder="Click or press S to search, ? for more options…" type="search"></div><button type="button" id="help-button" title="help">?</button><a id="settings-menu" href="../../settings.html" title="settings"><img width="18" height="18" alt="Change settings" src="../../wheel.svg"></a></div></form></nav><section id="main" 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>
</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</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">clap</span>::{<span class="ident">crate_version</span>, <span class="ident">App</span>, <span class="ident">AppSettings</span>, <span class="ident">Arg</span>, <span class="ident">ArgMatches</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="ident">stdin</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::num::ParseIntError</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::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_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="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">fn</span> <span class="ident">usage</span>() -&gt; <span class="ident">String</span> {
<span class="macro">format!</span>(
<span class="string">&quot;{0} [OPTION]... [INPUT [PREFIX]]&quot;</span>,
<span class="ident">uucore::execution_phrase</span>()
)
}
<span class="kw">fn</span> <span class="ident">get_long_usage</span>() -&gt; <span class="ident">String</span> {
<span class="macro">format!</span>(
<span class="string">&quot;Usage:
{0}
Output fixed-size pieces of INPUT to PREFIXaa, PREFIX ab, ...; 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="ident">usage</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">usage</span> <span class="op">=</span> <span class="ident">usage</span>();
<span class="kw">let</span> <span class="ident">long_usage</span> <span class="op">=</span> <span class="ident">get_long_usage</span>();
<span class="kw">let</span> <span class="ident">matches</span> <span class="op">=</span> <span class="ident">uu_app</span>()
.<span class="ident">override_usage</span>(<span class="kw-2">&amp;</span><span class="ident">usage</span>[..])
.<span class="ident">after_help</span>(<span class="kw-2">&amp;</span><span class="ident">long_usage</span>[..])
.<span class="ident">get_matches_from</span>(<span class="ident">args</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">App</span><span class="op">&lt;</span><span class="lifetime">&#39;a</span><span class="op">&gt;</span> {
<span class="ident">App::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">setting</span>(<span class="ident">AppSettings::InferLongArgs</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">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">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">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">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">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">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_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">default_value</span>(<span class="ident">OPT_DEFAULT_SUFFIX_LENGTH</span>)
.<span class="ident">help</span>(<span class="string">&quot;use suffixes of length N (default 2)&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">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">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">/// 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">usize</span>),
<span class="doccomment">/// Each chunk has the specified number of bytes.</span>
<span class="ident">Bytes</span>(<span class="ident">usize</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">usize</span>),
<span class="doccomment">/// Split the file into this many chunks.</span>
<span class="ident">Number</span>(<span class="ident">usize</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 of chunks.</span>
<span class="ident">NumberOfChunks</span>(<span class="ident">ParseIntError</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>::NumberOfChunks</span>(<span class="ident">e</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">e</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">occurrences_of</span>(<span class="ident">OPT_LINES</span>),
<span class="ident">matches</span>.<span class="ident">occurrences_of</span>(<span class="ident">OPT_BYTES</span>),
<span class="ident">matches</span>.<span class="ident">occurrences_of</span>(<span class="ident">OPT_LINE_BYTES</span>),
<span class="ident">matches</span>.<span class="ident">occurrences_of</span>(<span class="ident">OPT_NUMBER</span>),
) {
(<span class="number">0</span>, <span class="number">0</span>, <span class="number">0</span>, <span class="number">0</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="number">1</span>, <span class="number">0</span>, <span class="number">0</span>, <span class="number">0</span>) =&gt; {
<span class="kw">let</span> <span class="ident">s</span> <span class="op">=</span> <span class="ident">matches</span>.<span class="ident">value_of</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="number">0</span>, <span class="number">1</span>, <span class="number">0</span>, <span class="number">0</span>) =&gt; {
<span class="kw">let</span> <span class="ident">s</span> <span class="op">=</span> <span class="ident">matches</span>.<span class="ident">value_of</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="number">0</span>, <span class="number">0</span>, <span class="number">1</span>, <span class="number">0</span>) =&gt; {
<span class="kw">let</span> <span class="ident">s</span> <span class="op">=</span> <span class="ident">matches</span>.<span class="ident">value_of</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="number">0</span>, <span class="number">0</span>, <span class="number">0</span>, <span class="number">1</span>) =&gt; {
<span class="kw">let</span> <span class="ident">s</span> <span class="op">=</span> <span class="ident">matches</span>.<span class="ident">value_of</span>(<span class="ident">OPT_NUMBER</span>).<span class="ident">unwrap</span>();
<span class="kw">let</span> <span class="ident">n</span> <span class="op">=</span> <span class="ident">s</span>.<span class="ident">parse</span>::<span class="op">&lt;</span><span class="ident">usize</span><span class="op">&gt;</span>().<span class="ident">map_err</span>(<span class="ident">StrategyError::NumberOfChunks</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">n</span>))
}
<span class="kw">_</span> =&gt; <span class="prelude-val">Err</span>(<span class="ident">StrategyError::MultipleWays</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">numeric_suffix</span>: <span class="ident">bool</span>,
<span class="ident">suffix_length</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">/// 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">SuffixLength</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">/// 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>::SuffixLength</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>::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">value_of</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">suffix_length_str</span> <span class="op">=</span> <span class="ident">matches</span>.<span class="ident">value_of</span>(<span class="ident">OPT_SUFFIX_LENGTH</span>).<span class="ident">unwrap</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::SuffixLength</span>(<span class="ident">suffix_length_str</span>.<span class="ident">to_string</span>()))<span class="question-mark">?</span>,
<span class="ident">numeric_suffix</span>: <span class="ident">matches</span>.<span class="ident">occurrences_of</span>(<span class="ident">OPT_NUMERIC_SUFFIXES</span>) <span class="op">&gt;</span> <span class="number">0</span>,
<span class="ident">additional_suffix</span>,
<span class="ident">verbose</span>: <span class="ident">matches</span>.<span class="ident">occurrences_of</span>(<span class="string">&quot;verbose&quot;</span>) <span class="op">&gt;</span> <span class="number">0</span>,
<span class="ident">strategy</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="ident">input</span>: <span class="ident">matches</span>.<span class="ident">value_of</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">value_of</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">value_of</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="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="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">usize</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 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">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">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">usize</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="prelude-ty">Option</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">numeric_suffix</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="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">platform::instantiate_current_writer</span>(<span class="kw-2">&amp;</span><span class="ident">settings</span>.<span class="ident">filter</span>, <span class="kw-2">&amp;</span><span class="ident">filename</span>);
<span class="prelude-val">Some</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="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="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="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">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="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">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="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="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">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">// Increment the chunk number, reset the number of</span>
<span class="comment">// bytes remaining, and instantiate the new</span>
<span class="comment">// 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">// 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="comment">// Only create the writer for the next chunk if</span>
<span class="comment">// there are any remaining bytes to write. This</span>
<span class="comment">// check prevents us from creating a new empty</span>
<span class="comment">// file.</span>
<span class="kw">if</span> <span class="op">!</span><span class="ident">buf</span>.<span class="ident">is_empty</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="ident">platform::instantiate_current_writer</span>(<span class="kw-2">&amp;</span><span class="self">self</span>.<span class="ident">settings</span>.<span class="ident">filter</span>, <span class="kw-2">&amp;</span><span class="ident">filename</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">usize</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 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">usize</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">usize</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="prelude-ty">Option</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">numeric_suffix</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="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">platform::instantiate_current_writer</span>(<span class="kw-2">&amp;</span><span class="ident">settings</span>.<span class="ident">filter</span>, <span class="kw-2">&amp;</span><span class="ident">filename</span>);
<span class="prelude-val">Some</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="ident">platform::instantiate_current_writer</span>(<span class="kw-2">&amp;</span><span class="self">self</span>.<span class="ident">settings</span>.<span class="ident">filter</span>, <span class="kw-2">&amp;</span><span class="ident">filename</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">/// 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">usize</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="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">numeric_suffix</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">platform::instantiate_current_writer</span>(<span class="kw-2">&amp;</span><span class="ident">settings</span>.<span class="ident">filter</span>, <span class="ident">filename</span>.<span class="ident">as_str</span>());
<span class="ident">writers</span>.<span class="ident">push</span>(<span class="ident">writer</span>);
}
<span class="comment">// This block evaluates to an object of type `std::io::Result&lt;()&gt;`.</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">// Re-use the buffer to avoid re-allocating a `Vec` on each</span>
<span class="comment">// iteration. The contents will be completely overwritten each</span>
<span class="comment">// time we call `read_exact()`.</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">let</span> <span class="kw-2">mut</span> <span class="ident">buf</span> <span class="op">=</span> <span class="macro">vec!</span>[<span class="number">0u8</span>; <span class="ident">chunk_size</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">reader</span>.<span class="ident">read_exact</span>(<span class="kw-2">&amp;mut</span> <span class="ident">buf</span>)<span class="question-mark">?</span>;
<span class="ident">writer</span>.<span class="ident">write_all</span>(<span class="kw-2">&amp;</span><span class="ident">buf</span>)<span class="question-mark">?</span>;
}
<span class="comment">// Write all the remaining bytes to the last chunk.</span>
<span class="comment">//</span>
<span class="comment">// To do this, we resize our buffer to have the necessary number</span>
<span class="comment">// of bytes.</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="kw">as</span> <span class="ident">usize</span> <span class="op">-</span> (<span class="ident">chunk_size</span> <span class="op">*</span> (<span class="ident">num_chunks</span> <span class="op">-</span> <span class="number">1</span>));
<span class="ident">buf</span>.<span class="ident">resize</span>(<span class="ident">last_chunk_size</span>, <span class="number">0</span>);
<span class="ident">reader</span>.<span class="ident">read_exact</span>(<span class="kw-2">&amp;mut</span> <span class="ident">buf</span>)<span class="question-mark">?</span>;
<span class="ident">writers</span>[<span class="ident">i</span>].<span class="ident">write_all</span>(<span class="kw-2">&amp;</span><span class="ident">buf</span>)<span class="question-mark">?</span>;
<span class="prelude-val">Ok</span>(())
}
.<span class="ident">map_err_context</span>(<span class="op">|</span><span class="op">|</span> <span class="string">&quot;I/O error&quot;</span>.<span class="ident">to_string</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">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::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="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">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="string">&quot;output file suffixes exhausted&quot;</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>) <span class="op">|</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">ByteChunkWriter::new</span>(<span class="ident">chunk_size</span>, <span class="ident">settings</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">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="string">&quot;output file suffixes exhausted&quot;</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>)),
},
}
}
}
}
</code></pre></div>
</section><section id="search" class="content hidden"></section><div id="rustdoc-vars" data-root-path="../../" data-current-crate="uu_split" data-search-index-js="../../search-index.js" data-search-js="../../search.js"></div>
</body></html>