Adding large folders

This commit is contained in:
2026-02-26 12:00:21 -05:00
parent 5400d82acd
commit 49701c85ad
47332 changed files with 1942573 additions and 0 deletions

View File

@@ -0,0 +1,410 @@
<!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 `/home/newkirk/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/aho-corasick-1.1.4/src/util/alphabet.rs`."><title>alphabet.rs - source</title><script>if(window.location.protocol!=="file:")document.head.insertAdjacentHTML("beforeend","SourceSerif4-Regular-6b053e98.ttf.woff2,FiraSans-Italic-81dc35de.woff2,FiraSans-Regular-0fe48ade.woff2,FiraSans-MediumItalic-ccf7e434.woff2,FiraSans-Medium-e1aa3f0a.woff2,SourceCodePro-Regular-8badfe75.ttf.woff2,SourceCodePro-Semibold-aa29a496.ttf.woff2".split(",").map(f=>`<link rel="preload" as="font" type="font/woff2"href="../../../static.files/${f}">`).join(""))</script><link rel="stylesheet" href="../../../static.files/normalize-9960930a.css"><link rel="stylesheet" href="../../../static.files/rustdoc-ca0dd0c4.css"><meta name="rustdoc-vars" data-root-path="../../../" data-static-root-path="../../../static.files/" data-current-crate="aho_corasick" data-themes="" data-resource-suffix="" data-rustdoc-version="1.93.1 (01f6ddf75 2026-02-11) (Arch Linux rust 1:1.93.1-1)" data-channel="1.93.1" data-search-js="search-9e2438ea.js" data-stringdex-js="stringdex-a3946164.js" data-settings-js="settings-c38705f0.js" ><script src="../../../static.files/storage-e2aeef58.js"></script><script defer src="../../../static.files/src-script-813739b1.js"></script><script defer src="../../../src-files.js"></script><script defer src="../../../static.files/main-a410ff4d.js"></script><noscript><link rel="stylesheet" href="../../../static.files/noscript-263c88ec.css"></noscript><link rel="alternate icon" type="image/png" href="../../../static.files/favicon-32x32-eab170b8.png"><link rel="icon" type="image/svg+xml" href="../../../static.files/favicon-044be391.svg"></head><body class="rustdoc src"><!--[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="src-sidebar-title"><h2>Files</h2></div></nav><div class="sidebar-resizer" title="Drag to resize sidebar"></div><main><section id="main-content" class="content"><div class="main-heading"><h1><div class="sub-heading">aho_corasick/util/</div>alphabet.rs</h1><rustdoc-toolbar></rustdoc-toolbar></div><div class="example-wrap digits-3"><pre class="rust"><code><a href=#1 id=1 data-nosnippet>1</a><span class="kw">use </span><span class="kw">crate</span>::util::int::Usize;
<a href=#2 id=2 data-nosnippet>2</a>
<a href=#3 id=3 data-nosnippet>3</a><span class="doccomment">/// A representation of byte oriented equivalence classes.
<a href=#4 id=4 data-nosnippet>4</a>///
<a href=#5 id=5 data-nosnippet>5</a>/// This is used in finite state machines to reduce the size of the transition
<a href=#6 id=6 data-nosnippet>6</a>/// table. This can have a particularly large impact not only on the total size
<a href=#7 id=7 data-nosnippet>7</a>/// of an FSM, but also on FSM build times because it reduces the number of
<a href=#8 id=8 data-nosnippet>8</a>/// transitions that need to be visited/set.
<a href=#9 id=9 data-nosnippet>9</a></span><span class="attr">#[derive(Clone, Copy)]
<a href=#10 id=10 data-nosnippet>10</a></span><span class="kw">pub</span>(<span class="kw">crate</span>) <span class="kw">struct </span>ByteClasses([u8; <span class="number">256</span>]);
<a href=#11 id=11 data-nosnippet>11</a>
<a href=#12 id=12 data-nosnippet>12</a><span class="kw">impl </span>ByteClasses {
<a href=#13 id=13 data-nosnippet>13</a> <span class="doccomment">/// Creates a new set of equivalence classes where all bytes are mapped to
<a href=#14 id=14 data-nosnippet>14</a> /// the same class.
<a href=#15 id=15 data-nosnippet>15</a> </span><span class="kw">pub</span>(<span class="kw">crate</span>) <span class="kw">fn </span>empty() -&gt; ByteClasses {
<a href=#16 id=16 data-nosnippet>16</a> ByteClasses([<span class="number">0</span>; <span class="number">256</span>])
<a href=#17 id=17 data-nosnippet>17</a> }
<a href=#18 id=18 data-nosnippet>18</a>
<a href=#19 id=19 data-nosnippet>19</a> <span class="doccomment">/// Creates a new set of equivalence classes where each byte belongs to
<a href=#20 id=20 data-nosnippet>20</a> /// its own equivalence class.
<a href=#21 id=21 data-nosnippet>21</a> </span><span class="kw">pub</span>(<span class="kw">crate</span>) <span class="kw">fn </span>singletons() -&gt; ByteClasses {
<a href=#22 id=22 data-nosnippet>22</a> <span class="kw">let </span><span class="kw-2">mut </span>classes = ByteClasses::empty();
<a href=#23 id=23 data-nosnippet>23</a> <span class="kw">for </span>b <span class="kw">in </span><span class="number">0</span>..=<span class="number">255 </span>{
<a href=#24 id=24 data-nosnippet>24</a> classes.set(b, b);
<a href=#25 id=25 data-nosnippet>25</a> }
<a href=#26 id=26 data-nosnippet>26</a> classes
<a href=#27 id=27 data-nosnippet>27</a> }
<a href=#28 id=28 data-nosnippet>28</a>
<a href=#29 id=29 data-nosnippet>29</a> <span class="doccomment">/// Set the equivalence class for the given byte.
<a href=#30 id=30 data-nosnippet>30</a> </span><span class="attr">#[inline]
<a href=#31 id=31 data-nosnippet>31</a> </span><span class="kw">pub</span>(<span class="kw">crate</span>) <span class="kw">fn </span>set(<span class="kw-2">&amp;mut </span><span class="self">self</span>, byte: u8, class: u8) {
<a href=#32 id=32 data-nosnippet>32</a> <span class="self">self</span>.<span class="number">0</span>[usize::from(byte)] = class;
<a href=#33 id=33 data-nosnippet>33</a> }
<a href=#34 id=34 data-nosnippet>34</a>
<a href=#35 id=35 data-nosnippet>35</a> <span class="doccomment">/// Get the equivalence class for the given byte.
<a href=#36 id=36 data-nosnippet>36</a> </span><span class="attr">#[inline]
<a href=#37 id=37 data-nosnippet>37</a> </span><span class="kw">pub</span>(<span class="kw">crate</span>) <span class="kw">fn </span>get(<span class="kw-2">&amp;</span><span class="self">self</span>, byte: u8) -&gt; u8 {
<a href=#38 id=38 data-nosnippet>38</a> <span class="self">self</span>.<span class="number">0</span>[usize::from(byte)]
<a href=#39 id=39 data-nosnippet>39</a> }
<a href=#40 id=40 data-nosnippet>40</a>
<a href=#41 id=41 data-nosnippet>41</a> <span class="doccomment">/// Return the total number of elements in the alphabet represented by
<a href=#42 id=42 data-nosnippet>42</a> /// these equivalence classes. Equivalently, this returns the total number
<a href=#43 id=43 data-nosnippet>43</a> /// of equivalence classes.
<a href=#44 id=44 data-nosnippet>44</a> </span><span class="attr">#[inline]
<a href=#45 id=45 data-nosnippet>45</a> </span><span class="kw">pub</span>(<span class="kw">crate</span>) <span class="kw">fn </span>alphabet_len(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; usize {
<a href=#46 id=46 data-nosnippet>46</a> <span class="comment">// Add one since the number of equivalence classes is one bigger than
<a href=#47 id=47 data-nosnippet>47</a> // the last one.
<a href=#48 id=48 data-nosnippet>48</a> </span>usize::from(<span class="self">self</span>.<span class="number">0</span>[<span class="number">255</span>]) + <span class="number">1
<a href=#49 id=49 data-nosnippet>49</a> </span>}
<a href=#50 id=50 data-nosnippet>50</a>
<a href=#51 id=51 data-nosnippet>51</a> <span class="doccomment">/// Returns the stride, as a base-2 exponent, required for these
<a href=#52 id=52 data-nosnippet>52</a> /// equivalence classes.
<a href=#53 id=53 data-nosnippet>53</a> ///
<a href=#54 id=54 data-nosnippet>54</a> /// The stride is always the smallest power of 2 that is greater than or
<a href=#55 id=55 data-nosnippet>55</a> /// equal to the alphabet length. This is done so that converting between
<a href=#56 id=56 data-nosnippet>56</a> /// state IDs and indices can be done with shifts alone, which is much
<a href=#57 id=57 data-nosnippet>57</a> /// faster than integer division. The "stride2" is the exponent. i.e.,
<a href=#58 id=58 data-nosnippet>58</a> /// `2^stride2 = stride`.
<a href=#59 id=59 data-nosnippet>59</a> </span><span class="kw">pub</span>(<span class="kw">crate</span>) <span class="kw">fn </span>stride2(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; usize {
<a href=#60 id=60 data-nosnippet>60</a> <span class="kw">let </span>zeros = <span class="self">self</span>.alphabet_len().next_power_of_two().trailing_zeros();
<a href=#61 id=61 data-nosnippet>61</a> usize::try_from(zeros).unwrap()
<a href=#62 id=62 data-nosnippet>62</a> }
<a href=#63 id=63 data-nosnippet>63</a>
<a href=#64 id=64 data-nosnippet>64</a> <span class="doccomment">/// Returns the stride for these equivalence classes, which corresponds
<a href=#65 id=65 data-nosnippet>65</a> /// to the smallest power of 2 greater than or equal to the number of
<a href=#66 id=66 data-nosnippet>66</a> /// equivalence classes.
<a href=#67 id=67 data-nosnippet>67</a> </span><span class="kw">pub</span>(<span class="kw">crate</span>) <span class="kw">fn </span>stride(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; usize {
<a href=#68 id=68 data-nosnippet>68</a> <span class="number">1 </span>&lt;&lt; <span class="self">self</span>.stride2()
<a href=#69 id=69 data-nosnippet>69</a> }
<a href=#70 id=70 data-nosnippet>70</a>
<a href=#71 id=71 data-nosnippet>71</a> <span class="doccomment">/// Returns true if and only if every byte in this class maps to its own
<a href=#72 id=72 data-nosnippet>72</a> /// equivalence class. Equivalently, there are 257 equivalence classes
<a href=#73 id=73 data-nosnippet>73</a> /// and each class contains exactly one byte (plus the special EOI class).
<a href=#74 id=74 data-nosnippet>74</a> </span><span class="attr">#[inline]
<a href=#75 id=75 data-nosnippet>75</a> </span><span class="kw">pub</span>(<span class="kw">crate</span>) <span class="kw">fn </span>is_singleton(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; bool {
<a href=#76 id=76 data-nosnippet>76</a> <span class="self">self</span>.alphabet_len() == <span class="number">256
<a href=#77 id=77 data-nosnippet>77</a> </span>}
<a href=#78 id=78 data-nosnippet>78</a>
<a href=#79 id=79 data-nosnippet>79</a> <span class="doccomment">/// Returns an iterator over all equivalence classes in this set.
<a href=#80 id=80 data-nosnippet>80</a> </span><span class="kw">pub</span>(<span class="kw">crate</span>) <span class="kw">fn </span>iter(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; ByteClassIter {
<a href=#81 id=81 data-nosnippet>81</a> ByteClassIter { it: <span class="number">0</span>..<span class="self">self</span>.alphabet_len() }
<a href=#82 id=82 data-nosnippet>82</a> }
<a href=#83 id=83 data-nosnippet>83</a>
<a href=#84 id=84 data-nosnippet>84</a> <span class="doccomment">/// Returns an iterator of the bytes in the given equivalence class.
<a href=#85 id=85 data-nosnippet>85</a> </span><span class="kw">pub</span>(<span class="kw">crate</span>) <span class="kw">fn </span>elements(<span class="kw-2">&amp;</span><span class="self">self</span>, class: u8) -&gt; ByteClassElements {
<a href=#86 id=86 data-nosnippet>86</a> ByteClassElements { classes: <span class="self">self</span>, class, bytes: <span class="number">0</span>..=<span class="number">255 </span>}
<a href=#87 id=87 data-nosnippet>87</a> }
<a href=#88 id=88 data-nosnippet>88</a>
<a href=#89 id=89 data-nosnippet>89</a> <span class="doccomment">/// Returns an iterator of byte ranges in the given equivalence class.
<a href=#90 id=90 data-nosnippet>90</a> ///
<a href=#91 id=91 data-nosnippet>91</a> /// That is, a sequence of contiguous ranges are returned. Typically, every
<a href=#92 id=92 data-nosnippet>92</a> /// class maps to a single contiguous range.
<a href=#93 id=93 data-nosnippet>93</a> </span><span class="kw">fn </span>element_ranges(<span class="kw-2">&amp;</span><span class="self">self</span>, class: u8) -&gt; ByteClassElementRanges {
<a href=#94 id=94 data-nosnippet>94</a> ByteClassElementRanges { elements: <span class="self">self</span>.elements(class), range: <span class="prelude-val">None </span>}
<a href=#95 id=95 data-nosnippet>95</a> }
<a href=#96 id=96 data-nosnippet>96</a>}
<a href=#97 id=97 data-nosnippet>97</a>
<a href=#98 id=98 data-nosnippet>98</a><span class="kw">impl </span>core::fmt::Debug <span class="kw">for </span>ByteClasses {
<a href=#99 id=99 data-nosnippet>99</a> <span class="kw">fn </span>fmt(<span class="kw-2">&amp;</span><span class="self">self</span>, f: <span class="kw-2">&amp;mut </span>core::fmt::Formatter&lt;<span class="lifetime">'_</span>&gt;) -&gt; core::fmt::Result {
<a href=#100 id=100 data-nosnippet>100</a> <span class="kw">if </span><span class="self">self</span>.is_singleton() {
<a href=#101 id=101 data-nosnippet>101</a> <span class="macro">write!</span>(f, <span class="string">"ByteClasses(&lt;one-class-per-byte&gt;)"</span>)
<a href=#102 id=102 data-nosnippet>102</a> } <span class="kw">else </span>{
<a href=#103 id=103 data-nosnippet>103</a> <span class="macro">write!</span>(f, <span class="string">"ByteClasses("</span>)<span class="question-mark">?</span>;
<a href=#104 id=104 data-nosnippet>104</a> <span class="kw">for </span>(i, class) <span class="kw">in </span><span class="self">self</span>.iter().enumerate() {
<a href=#105 id=105 data-nosnippet>105</a> <span class="kw">if </span>i &gt; <span class="number">0 </span>{
<a href=#106 id=106 data-nosnippet>106</a> <span class="macro">write!</span>(f, <span class="string">", "</span>)<span class="question-mark">?</span>;
<a href=#107 id=107 data-nosnippet>107</a> }
<a href=#108 id=108 data-nosnippet>108</a> <span class="macro">write!</span>(f, <span class="string">"{:?} =&gt; ["</span>, class)<span class="question-mark">?</span>;
<a href=#109 id=109 data-nosnippet>109</a> <span class="kw">for </span>(start, end) <span class="kw">in </span><span class="self">self</span>.element_ranges(class) {
<a href=#110 id=110 data-nosnippet>110</a> <span class="kw">if </span>start == end {
<a href=#111 id=111 data-nosnippet>111</a> <span class="macro">write!</span>(f, <span class="string">"{:?}"</span>, start)<span class="question-mark">?</span>;
<a href=#112 id=112 data-nosnippet>112</a> } <span class="kw">else </span>{
<a href=#113 id=113 data-nosnippet>113</a> <span class="macro">write!</span>(f, <span class="string">"{:?}-{:?}"</span>, start, end)<span class="question-mark">?</span>;
<a href=#114 id=114 data-nosnippet>114</a> }
<a href=#115 id=115 data-nosnippet>115</a> }
<a href=#116 id=116 data-nosnippet>116</a> <span class="macro">write!</span>(f, <span class="string">"]"</span>)<span class="question-mark">?</span>;
<a href=#117 id=117 data-nosnippet>117</a> }
<a href=#118 id=118 data-nosnippet>118</a> <span class="macro">write!</span>(f, <span class="string">")"</span>)
<a href=#119 id=119 data-nosnippet>119</a> }
<a href=#120 id=120 data-nosnippet>120</a> }
<a href=#121 id=121 data-nosnippet>121</a>}
<a href=#122 id=122 data-nosnippet>122</a>
<a href=#123 id=123 data-nosnippet>123</a><span class="doccomment">/// An iterator over each equivalence class.
<a href=#124 id=124 data-nosnippet>124</a></span><span class="attr">#[derive(Debug)]
<a href=#125 id=125 data-nosnippet>125</a></span><span class="kw">pub</span>(<span class="kw">crate</span>) <span class="kw">struct </span>ByteClassIter {
<a href=#126 id=126 data-nosnippet>126</a> it: core::ops::Range&lt;usize&gt;,
<a href=#127 id=127 data-nosnippet>127</a>}
<a href=#128 id=128 data-nosnippet>128</a>
<a href=#129 id=129 data-nosnippet>129</a><span class="kw">impl </span>Iterator <span class="kw">for </span>ByteClassIter {
<a href=#130 id=130 data-nosnippet>130</a> <span class="kw">type </span>Item = u8;
<a href=#131 id=131 data-nosnippet>131</a>
<a href=#132 id=132 data-nosnippet>132</a> <span class="kw">fn </span>next(<span class="kw-2">&amp;mut </span><span class="self">self</span>) -&gt; <span class="prelude-ty">Option</span>&lt;u8&gt; {
<a href=#133 id=133 data-nosnippet>133</a> <span class="self">self</span>.it.next().map(|class| class.as_u8())
<a href=#134 id=134 data-nosnippet>134</a> }
<a href=#135 id=135 data-nosnippet>135</a>}
<a href=#136 id=136 data-nosnippet>136</a>
<a href=#137 id=137 data-nosnippet>137</a><span class="doccomment">/// An iterator over all elements in a specific equivalence class.
<a href=#138 id=138 data-nosnippet>138</a></span><span class="attr">#[derive(Debug)]
<a href=#139 id=139 data-nosnippet>139</a></span><span class="kw">pub</span>(<span class="kw">crate</span>) <span class="kw">struct </span>ByteClassElements&lt;<span class="lifetime">'a</span>&gt; {
<a href=#140 id=140 data-nosnippet>140</a> classes: <span class="kw-2">&amp;</span><span class="lifetime">'a </span>ByteClasses,
<a href=#141 id=141 data-nosnippet>141</a> class: u8,
<a href=#142 id=142 data-nosnippet>142</a> bytes: core::ops::RangeInclusive&lt;u8&gt;,
<a href=#143 id=143 data-nosnippet>143</a>}
<a href=#144 id=144 data-nosnippet>144</a>
<a href=#145 id=145 data-nosnippet>145</a><span class="kw">impl</span>&lt;<span class="lifetime">'a</span>&gt; Iterator <span class="kw">for </span>ByteClassElements&lt;<span class="lifetime">'a</span>&gt; {
<a href=#146 id=146 data-nosnippet>146</a> <span class="kw">type </span>Item = u8;
<a href=#147 id=147 data-nosnippet>147</a>
<a href=#148 id=148 data-nosnippet>148</a> <span class="kw">fn </span>next(<span class="kw-2">&amp;mut </span><span class="self">self</span>) -&gt; <span class="prelude-ty">Option</span>&lt;u8&gt; {
<a href=#149 id=149 data-nosnippet>149</a> <span class="kw">while let </span><span class="prelude-val">Some</span>(byte) = <span class="self">self</span>.bytes.next() {
<a href=#150 id=150 data-nosnippet>150</a> <span class="kw">if </span><span class="self">self</span>.class == <span class="self">self</span>.classes.get(byte) {
<a href=#151 id=151 data-nosnippet>151</a> <span class="kw">return </span><span class="prelude-val">Some</span>(byte);
<a href=#152 id=152 data-nosnippet>152</a> }
<a href=#153 id=153 data-nosnippet>153</a> }
<a href=#154 id=154 data-nosnippet>154</a> <span class="prelude-val">None
<a href=#155 id=155 data-nosnippet>155</a> </span>}
<a href=#156 id=156 data-nosnippet>156</a>}
<a href=#157 id=157 data-nosnippet>157</a>
<a href=#158 id=158 data-nosnippet>158</a><span class="doccomment">/// An iterator over all elements in an equivalence class expressed as a
<a href=#159 id=159 data-nosnippet>159</a>/// sequence of contiguous ranges.
<a href=#160 id=160 data-nosnippet>160</a></span><span class="attr">#[derive(Debug)]
<a href=#161 id=161 data-nosnippet>161</a></span><span class="kw">pub</span>(<span class="kw">crate</span>) <span class="kw">struct </span>ByteClassElementRanges&lt;<span class="lifetime">'a</span>&gt; {
<a href=#162 id=162 data-nosnippet>162</a> elements: ByteClassElements&lt;<span class="lifetime">'a</span>&gt;,
<a href=#163 id=163 data-nosnippet>163</a> range: <span class="prelude-ty">Option</span>&lt;(u8, u8)&gt;,
<a href=#164 id=164 data-nosnippet>164</a>}
<a href=#165 id=165 data-nosnippet>165</a>
<a href=#166 id=166 data-nosnippet>166</a><span class="kw">impl</span>&lt;<span class="lifetime">'a</span>&gt; Iterator <span class="kw">for </span>ByteClassElementRanges&lt;<span class="lifetime">'a</span>&gt; {
<a href=#167 id=167 data-nosnippet>167</a> <span class="kw">type </span>Item = (u8, u8);
<a href=#168 id=168 data-nosnippet>168</a>
<a href=#169 id=169 data-nosnippet>169</a> <span class="kw">fn </span>next(<span class="kw-2">&amp;mut </span><span class="self">self</span>) -&gt; <span class="prelude-ty">Option</span>&lt;(u8, u8)&gt; {
<a href=#170 id=170 data-nosnippet>170</a> <span class="kw">loop </span>{
<a href=#171 id=171 data-nosnippet>171</a> <span class="kw">let </span>element = <span class="kw">match </span><span class="self">self</span>.elements.next() {
<a href=#172 id=172 data-nosnippet>172</a> <span class="prelude-val">None </span>=&gt; <span class="kw">return </span><span class="self">self</span>.range.take(),
<a href=#173 id=173 data-nosnippet>173</a> <span class="prelude-val">Some</span>(element) =&gt; element,
<a href=#174 id=174 data-nosnippet>174</a> };
<a href=#175 id=175 data-nosnippet>175</a> <span class="kw">match </span><span class="self">self</span>.range.take() {
<a href=#176 id=176 data-nosnippet>176</a> <span class="prelude-val">None </span>=&gt; {
<a href=#177 id=177 data-nosnippet>177</a> <span class="self">self</span>.range = <span class="prelude-val">Some</span>((element, element));
<a href=#178 id=178 data-nosnippet>178</a> }
<a href=#179 id=179 data-nosnippet>179</a> <span class="prelude-val">Some</span>((start, end)) =&gt; {
<a href=#180 id=180 data-nosnippet>180</a> <span class="kw">if </span>usize::from(end) + <span class="number">1 </span>!= usize::from(element) {
<a href=#181 id=181 data-nosnippet>181</a> <span class="self">self</span>.range = <span class="prelude-val">Some</span>((element, element));
<a href=#182 id=182 data-nosnippet>182</a> <span class="kw">return </span><span class="prelude-val">Some</span>((start, end));
<a href=#183 id=183 data-nosnippet>183</a> }
<a href=#184 id=184 data-nosnippet>184</a> <span class="self">self</span>.range = <span class="prelude-val">Some</span>((start, element));
<a href=#185 id=185 data-nosnippet>185</a> }
<a href=#186 id=186 data-nosnippet>186</a> }
<a href=#187 id=187 data-nosnippet>187</a> }
<a href=#188 id=188 data-nosnippet>188</a> }
<a href=#189 id=189 data-nosnippet>189</a>}
<a href=#190 id=190 data-nosnippet>190</a>
<a href=#191 id=191 data-nosnippet>191</a><span class="doccomment">/// A partitioning of bytes into equivalence classes.
<a href=#192 id=192 data-nosnippet>192</a>///
<a href=#193 id=193 data-nosnippet>193</a>/// A byte class set keeps track of an *approximation* of equivalence classes
<a href=#194 id=194 data-nosnippet>194</a>/// of bytes during NFA construction. That is, every byte in an equivalence
<a href=#195 id=195 data-nosnippet>195</a>/// class cannot discriminate between a match and a non-match.
<a href=#196 id=196 data-nosnippet>196</a>///
<a href=#197 id=197 data-nosnippet>197</a>/// Note that this may not compute the minimal set of equivalence classes.
<a href=#198 id=198 data-nosnippet>198</a>/// Basically, any byte in a pattern given to the noncontiguous NFA builder
<a href=#199 id=199 data-nosnippet>199</a>/// will automatically be treated as its own equivalence class. All other
<a href=#200 id=200 data-nosnippet>200</a>/// bytes---any byte not in any pattern---will be treated as their own
<a href=#201 id=201 data-nosnippet>201</a>/// equivalence classes. In theory, all bytes not in any pattern should
<a href=#202 id=202 data-nosnippet>202</a>/// be part of a single equivalence class, but in practice, we only treat
<a href=#203 id=203 data-nosnippet>203</a>/// contiguous ranges of bytes as an equivalence class. So the number of
<a href=#204 id=204 data-nosnippet>204</a>/// classes computed may be bigger than necessary. This usually doesn't make
<a href=#205 id=205 data-nosnippet>205</a>/// much of a difference, and keeps the implementation simple.
<a href=#206 id=206 data-nosnippet>206</a></span><span class="attr">#[derive(Clone, Debug)]
<a href=#207 id=207 data-nosnippet>207</a></span><span class="kw">pub</span>(<span class="kw">crate</span>) <span class="kw">struct </span>ByteClassSet(ByteSet);
<a href=#208 id=208 data-nosnippet>208</a>
<a href=#209 id=209 data-nosnippet>209</a><span class="kw">impl </span>Default <span class="kw">for </span>ByteClassSet {
<a href=#210 id=210 data-nosnippet>210</a> <span class="kw">fn </span>default() -&gt; ByteClassSet {
<a href=#211 id=211 data-nosnippet>211</a> ByteClassSet::empty()
<a href=#212 id=212 data-nosnippet>212</a> }
<a href=#213 id=213 data-nosnippet>213</a>}
<a href=#214 id=214 data-nosnippet>214</a>
<a href=#215 id=215 data-nosnippet>215</a><span class="kw">impl </span>ByteClassSet {
<a href=#216 id=216 data-nosnippet>216</a> <span class="doccomment">/// Create a new set of byte classes where all bytes are part of the same
<a href=#217 id=217 data-nosnippet>217</a> /// equivalence class.
<a href=#218 id=218 data-nosnippet>218</a> </span><span class="kw">pub</span>(<span class="kw">crate</span>) <span class="kw">fn </span>empty() -&gt; <span class="self">Self </span>{
<a href=#219 id=219 data-nosnippet>219</a> ByteClassSet(ByteSet::empty())
<a href=#220 id=220 data-nosnippet>220</a> }
<a href=#221 id=221 data-nosnippet>221</a>
<a href=#222 id=222 data-nosnippet>222</a> <span class="doccomment">/// Indicate the the range of byte given (inclusive) can discriminate a
<a href=#223 id=223 data-nosnippet>223</a> /// match between it and all other bytes outside of the range.
<a href=#224 id=224 data-nosnippet>224</a> </span><span class="kw">pub</span>(<span class="kw">crate</span>) <span class="kw">fn </span>set_range(<span class="kw-2">&amp;mut </span><span class="self">self</span>, start: u8, end: u8) {
<a href=#225 id=225 data-nosnippet>225</a> <span class="macro">debug_assert!</span>(start &lt;= end);
<a href=#226 id=226 data-nosnippet>226</a> <span class="kw">if </span>start &gt; <span class="number">0 </span>{
<a href=#227 id=227 data-nosnippet>227</a> <span class="self">self</span>.<span class="number">0</span>.add(start - <span class="number">1</span>);
<a href=#228 id=228 data-nosnippet>228</a> }
<a href=#229 id=229 data-nosnippet>229</a> <span class="self">self</span>.<span class="number">0</span>.add(end);
<a href=#230 id=230 data-nosnippet>230</a> }
<a href=#231 id=231 data-nosnippet>231</a>
<a href=#232 id=232 data-nosnippet>232</a> <span class="doccomment">/// Convert this boolean set to a map that maps all byte values to their
<a href=#233 id=233 data-nosnippet>233</a> /// corresponding equivalence class. The last mapping indicates the largest
<a href=#234 id=234 data-nosnippet>234</a> /// equivalence class identifier (which is never bigger than 255).
<a href=#235 id=235 data-nosnippet>235</a> </span><span class="kw">pub</span>(<span class="kw">crate</span>) <span class="kw">fn </span>byte_classes(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; ByteClasses {
<a href=#236 id=236 data-nosnippet>236</a> <span class="kw">let </span><span class="kw-2">mut </span>classes = ByteClasses::empty();
<a href=#237 id=237 data-nosnippet>237</a> <span class="kw">let </span><span class="kw-2">mut </span>class = <span class="number">0u8</span>;
<a href=#238 id=238 data-nosnippet>238</a> <span class="kw">let </span><span class="kw-2">mut </span>b = <span class="number">0u8</span>;
<a href=#239 id=239 data-nosnippet>239</a> <span class="kw">loop </span>{
<a href=#240 id=240 data-nosnippet>240</a> classes.set(b, class);
<a href=#241 id=241 data-nosnippet>241</a> <span class="kw">if </span>b == <span class="number">255 </span>{
<a href=#242 id=242 data-nosnippet>242</a> <span class="kw">break</span>;
<a href=#243 id=243 data-nosnippet>243</a> }
<a href=#244 id=244 data-nosnippet>244</a> <span class="kw">if </span><span class="self">self</span>.<span class="number">0</span>.contains(b) {
<a href=#245 id=245 data-nosnippet>245</a> class = class.checked_add(<span class="number">1</span>).unwrap();
<a href=#246 id=246 data-nosnippet>246</a> }
<a href=#247 id=247 data-nosnippet>247</a> b = b.checked_add(<span class="number">1</span>).unwrap();
<a href=#248 id=248 data-nosnippet>248</a> }
<a href=#249 id=249 data-nosnippet>249</a> classes
<a href=#250 id=250 data-nosnippet>250</a> }
<a href=#251 id=251 data-nosnippet>251</a>}
<a href=#252 id=252 data-nosnippet>252</a>
<a href=#253 id=253 data-nosnippet>253</a><span class="doccomment">/// A simple set of bytes that is reasonably cheap to copy and allocation free.
<a href=#254 id=254 data-nosnippet>254</a></span><span class="attr">#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
<a href=#255 id=255 data-nosnippet>255</a></span><span class="kw">pub</span>(<span class="kw">crate</span>) <span class="kw">struct </span>ByteSet {
<a href=#256 id=256 data-nosnippet>256</a> bits: BitSet,
<a href=#257 id=257 data-nosnippet>257</a>}
<a href=#258 id=258 data-nosnippet>258</a>
<a href=#259 id=259 data-nosnippet>259</a><span class="doccomment">/// The representation of a byte set. Split out so that we can define a
<a href=#260 id=260 data-nosnippet>260</a>/// convenient Debug impl for it while keeping "ByteSet" in the output.
<a href=#261 id=261 data-nosnippet>261</a></span><span class="attr">#[derive(Clone, Copy, Default, Eq, PartialEq)]
<a href=#262 id=262 data-nosnippet>262</a></span><span class="kw">struct </span>BitSet([u128; <span class="number">2</span>]);
<a href=#263 id=263 data-nosnippet>263</a>
<a href=#264 id=264 data-nosnippet>264</a><span class="kw">impl </span>ByteSet {
<a href=#265 id=265 data-nosnippet>265</a> <span class="doccomment">/// Create an empty set of bytes.
<a href=#266 id=266 data-nosnippet>266</a> </span><span class="kw">pub</span>(<span class="kw">crate</span>) <span class="kw">fn </span>empty() -&gt; ByteSet {
<a href=#267 id=267 data-nosnippet>267</a> ByteSet { bits: BitSet([<span class="number">0</span>; <span class="number">2</span>]) }
<a href=#268 id=268 data-nosnippet>268</a> }
<a href=#269 id=269 data-nosnippet>269</a>
<a href=#270 id=270 data-nosnippet>270</a> <span class="doccomment">/// Add a byte to this set.
<a href=#271 id=271 data-nosnippet>271</a> ///
<a href=#272 id=272 data-nosnippet>272</a> /// If the given byte already belongs to this set, then this is a no-op.
<a href=#273 id=273 data-nosnippet>273</a> </span><span class="kw">pub</span>(<span class="kw">crate</span>) <span class="kw">fn </span>add(<span class="kw-2">&amp;mut </span><span class="self">self</span>, byte: u8) {
<a href=#274 id=274 data-nosnippet>274</a> <span class="kw">let </span>bucket = byte / <span class="number">128</span>;
<a href=#275 id=275 data-nosnippet>275</a> <span class="kw">let </span>bit = byte % <span class="number">128</span>;
<a href=#276 id=276 data-nosnippet>276</a> <span class="self">self</span>.bits.<span class="number">0</span>[usize::from(bucket)] |= <span class="number">1 </span>&lt;&lt; bit;
<a href=#277 id=277 data-nosnippet>277</a> }
<a href=#278 id=278 data-nosnippet>278</a>
<a href=#279 id=279 data-nosnippet>279</a> <span class="doccomment">/// Return true if and only if the given byte is in this set.
<a href=#280 id=280 data-nosnippet>280</a> </span><span class="kw">pub</span>(<span class="kw">crate</span>) <span class="kw">fn </span>contains(<span class="kw-2">&amp;</span><span class="self">self</span>, byte: u8) -&gt; bool {
<a href=#281 id=281 data-nosnippet>281</a> <span class="kw">let </span>bucket = byte / <span class="number">128</span>;
<a href=#282 id=282 data-nosnippet>282</a> <span class="kw">let </span>bit = byte % <span class="number">128</span>;
<a href=#283 id=283 data-nosnippet>283</a> <span class="self">self</span>.bits.<span class="number">0</span>[usize::from(bucket)] &amp; (<span class="number">1 </span>&lt;&lt; bit) &gt; <span class="number">0
<a href=#284 id=284 data-nosnippet>284</a> </span>}
<a href=#285 id=285 data-nosnippet>285</a>}
<a href=#286 id=286 data-nosnippet>286</a>
<a href=#287 id=287 data-nosnippet>287</a><span class="kw">impl </span>core::fmt::Debug <span class="kw">for </span>BitSet {
<a href=#288 id=288 data-nosnippet>288</a> <span class="kw">fn </span>fmt(<span class="kw-2">&amp;</span><span class="self">self</span>, f: <span class="kw-2">&amp;mut </span>core::fmt::Formatter) -&gt; core::fmt::Result {
<a href=#289 id=289 data-nosnippet>289</a> <span class="kw">let </span><span class="kw-2">mut </span>fmtd = f.debug_set();
<a href=#290 id=290 data-nosnippet>290</a> <span class="kw">for </span>b <span class="kw">in </span><span class="number">0u8</span>..=<span class="number">255 </span>{
<a href=#291 id=291 data-nosnippet>291</a> <span class="kw">if </span>(ByteSet { bits: <span class="kw-2">*</span><span class="self">self </span>}).contains(b) {
<a href=#292 id=292 data-nosnippet>292</a> fmtd.entry(<span class="kw-2">&amp;</span>b);
<a href=#293 id=293 data-nosnippet>293</a> }
<a href=#294 id=294 data-nosnippet>294</a> }
<a href=#295 id=295 data-nosnippet>295</a> fmtd.finish()
<a href=#296 id=296 data-nosnippet>296</a> }
<a href=#297 id=297 data-nosnippet>297</a>}
<a href=#298 id=298 data-nosnippet>298</a>
<a href=#299 id=299 data-nosnippet>299</a><span class="attr">#[cfg(test)]
<a href=#300 id=300 data-nosnippet>300</a></span><span class="kw">mod </span>tests {
<a href=#301 id=301 data-nosnippet>301</a> <span class="kw">use </span>alloc::{vec, vec::Vec};
<a href=#302 id=302 data-nosnippet>302</a>
<a href=#303 id=303 data-nosnippet>303</a> <span class="kw">use super</span>::<span class="kw-2">*</span>;
<a href=#304 id=304 data-nosnippet>304</a>
<a href=#305 id=305 data-nosnippet>305</a> <span class="attr">#[test]
<a href=#306 id=306 data-nosnippet>306</a> </span><span class="kw">fn </span>byte_classes() {
<a href=#307 id=307 data-nosnippet>307</a> <span class="kw">let </span><span class="kw-2">mut </span>set = ByteClassSet::empty();
<a href=#308 id=308 data-nosnippet>308</a> set.set_range(<span class="string">b'a'</span>, <span class="string">b'z'</span>);
<a href=#309 id=309 data-nosnippet>309</a>
<a href=#310 id=310 data-nosnippet>310</a> <span class="kw">let </span>classes = set.byte_classes();
<a href=#311 id=311 data-nosnippet>311</a> <span class="macro">assert_eq!</span>(classes.get(<span class="number">0</span>), <span class="number">0</span>);
<a href=#312 id=312 data-nosnippet>312</a> <span class="macro">assert_eq!</span>(classes.get(<span class="number">1</span>), <span class="number">0</span>);
<a href=#313 id=313 data-nosnippet>313</a> <span class="macro">assert_eq!</span>(classes.get(<span class="number">2</span>), <span class="number">0</span>);
<a href=#314 id=314 data-nosnippet>314</a> <span class="macro">assert_eq!</span>(classes.get(<span class="string">b'a' </span>- <span class="number">1</span>), <span class="number">0</span>);
<a href=#315 id=315 data-nosnippet>315</a> <span class="macro">assert_eq!</span>(classes.get(<span class="string">b'a'</span>), <span class="number">1</span>);
<a href=#316 id=316 data-nosnippet>316</a> <span class="macro">assert_eq!</span>(classes.get(<span class="string">b'm'</span>), <span class="number">1</span>);
<a href=#317 id=317 data-nosnippet>317</a> <span class="macro">assert_eq!</span>(classes.get(<span class="string">b'z'</span>), <span class="number">1</span>);
<a href=#318 id=318 data-nosnippet>318</a> <span class="macro">assert_eq!</span>(classes.get(<span class="string">b'z' </span>+ <span class="number">1</span>), <span class="number">2</span>);
<a href=#319 id=319 data-nosnippet>319</a> <span class="macro">assert_eq!</span>(classes.get(<span class="number">254</span>), <span class="number">2</span>);
<a href=#320 id=320 data-nosnippet>320</a> <span class="macro">assert_eq!</span>(classes.get(<span class="number">255</span>), <span class="number">2</span>);
<a href=#321 id=321 data-nosnippet>321</a>
<a href=#322 id=322 data-nosnippet>322</a> <span class="kw">let </span><span class="kw-2">mut </span>set = ByteClassSet::empty();
<a href=#323 id=323 data-nosnippet>323</a> set.set_range(<span class="number">0</span>, <span class="number">2</span>);
<a href=#324 id=324 data-nosnippet>324</a> set.set_range(<span class="number">4</span>, <span class="number">6</span>);
<a href=#325 id=325 data-nosnippet>325</a> <span class="kw">let </span>classes = set.byte_classes();
<a href=#326 id=326 data-nosnippet>326</a> <span class="macro">assert_eq!</span>(classes.get(<span class="number">0</span>), <span class="number">0</span>);
<a href=#327 id=327 data-nosnippet>327</a> <span class="macro">assert_eq!</span>(classes.get(<span class="number">1</span>), <span class="number">0</span>);
<a href=#328 id=328 data-nosnippet>328</a> <span class="macro">assert_eq!</span>(classes.get(<span class="number">2</span>), <span class="number">0</span>);
<a href=#329 id=329 data-nosnippet>329</a> <span class="macro">assert_eq!</span>(classes.get(<span class="number">3</span>), <span class="number">1</span>);
<a href=#330 id=330 data-nosnippet>330</a> <span class="macro">assert_eq!</span>(classes.get(<span class="number">4</span>), <span class="number">2</span>);
<a href=#331 id=331 data-nosnippet>331</a> <span class="macro">assert_eq!</span>(classes.get(<span class="number">5</span>), <span class="number">2</span>);
<a href=#332 id=332 data-nosnippet>332</a> <span class="macro">assert_eq!</span>(classes.get(<span class="number">6</span>), <span class="number">2</span>);
<a href=#333 id=333 data-nosnippet>333</a> <span class="macro">assert_eq!</span>(classes.get(<span class="number">7</span>), <span class="number">3</span>);
<a href=#334 id=334 data-nosnippet>334</a> <span class="macro">assert_eq!</span>(classes.get(<span class="number">255</span>), <span class="number">3</span>);
<a href=#335 id=335 data-nosnippet>335</a> }
<a href=#336 id=336 data-nosnippet>336</a>
<a href=#337 id=337 data-nosnippet>337</a> <span class="attr">#[test]
<a href=#338 id=338 data-nosnippet>338</a> </span><span class="kw">fn </span>full_byte_classes() {
<a href=#339 id=339 data-nosnippet>339</a> <span class="kw">let </span><span class="kw-2">mut </span>set = ByteClassSet::empty();
<a href=#340 id=340 data-nosnippet>340</a> <span class="kw">for </span>b <span class="kw">in </span><span class="number">0u8</span>..=<span class="number">255 </span>{
<a href=#341 id=341 data-nosnippet>341</a> set.set_range(b, b);
<a href=#342 id=342 data-nosnippet>342</a> }
<a href=#343 id=343 data-nosnippet>343</a> <span class="macro">assert_eq!</span>(set.byte_classes().alphabet_len(), <span class="number">256</span>);
<a href=#344 id=344 data-nosnippet>344</a> }
<a href=#345 id=345 data-nosnippet>345</a>
<a href=#346 id=346 data-nosnippet>346</a> <span class="attr">#[test]
<a href=#347 id=347 data-nosnippet>347</a> </span><span class="kw">fn </span>elements_typical() {
<a href=#348 id=348 data-nosnippet>348</a> <span class="kw">let </span><span class="kw-2">mut </span>set = ByteClassSet::empty();
<a href=#349 id=349 data-nosnippet>349</a> set.set_range(<span class="string">b'b'</span>, <span class="string">b'd'</span>);
<a href=#350 id=350 data-nosnippet>350</a> set.set_range(<span class="string">b'g'</span>, <span class="string">b'm'</span>);
<a href=#351 id=351 data-nosnippet>351</a> set.set_range(<span class="string">b'z'</span>, <span class="string">b'z'</span>);
<a href=#352 id=352 data-nosnippet>352</a> <span class="kw">let </span>classes = set.byte_classes();
<a href=#353 id=353 data-nosnippet>353</a> <span class="comment">// class 0: \x00-a
<a href=#354 id=354 data-nosnippet>354</a> // class 1: b-d
<a href=#355 id=355 data-nosnippet>355</a> // class 2: e-f
<a href=#356 id=356 data-nosnippet>356</a> // class 3: g-m
<a href=#357 id=357 data-nosnippet>357</a> // class 4: n-y
<a href=#358 id=358 data-nosnippet>358</a> // class 5: z-z
<a href=#359 id=359 data-nosnippet>359</a> // class 6: \x7B-\xFF
<a href=#360 id=360 data-nosnippet>360</a> </span><span class="macro">assert_eq!</span>(classes.alphabet_len(), <span class="number">7</span>);
<a href=#361 id=361 data-nosnippet>361</a>
<a href=#362 id=362 data-nosnippet>362</a> <span class="kw">let </span>elements = classes.elements(<span class="number">0</span>).collect::&lt;Vec&lt;<span class="kw">_</span>&gt;&gt;();
<a href=#363 id=363 data-nosnippet>363</a> <span class="macro">assert_eq!</span>(elements.len(), <span class="number">98</span>);
<a href=#364 id=364 data-nosnippet>364</a> <span class="macro">assert_eq!</span>(elements[<span class="number">0</span>], <span class="string">b'\x00'</span>);
<a href=#365 id=365 data-nosnippet>365</a> <span class="macro">assert_eq!</span>(elements[<span class="number">97</span>], <span class="string">b'a'</span>);
<a href=#366 id=366 data-nosnippet>366</a>
<a href=#367 id=367 data-nosnippet>367</a> <span class="kw">let </span>elements = classes.elements(<span class="number">1</span>).collect::&lt;Vec&lt;<span class="kw">_</span>&gt;&gt;();
<a href=#368 id=368 data-nosnippet>368</a> <span class="macro">assert_eq!</span>(elements, <span class="macro">vec!</span>[<span class="string">b'b'</span>, <span class="string">b'c'</span>, <span class="string">b'd'</span>],);
<a href=#369 id=369 data-nosnippet>369</a>
<a href=#370 id=370 data-nosnippet>370</a> <span class="kw">let </span>elements = classes.elements(<span class="number">2</span>).collect::&lt;Vec&lt;<span class="kw">_</span>&gt;&gt;();
<a href=#371 id=371 data-nosnippet>371</a> <span class="macro">assert_eq!</span>(elements, <span class="macro">vec!</span>[<span class="string">b'e'</span>, <span class="string">b'f'</span>],);
<a href=#372 id=372 data-nosnippet>372</a>
<a href=#373 id=373 data-nosnippet>373</a> <span class="kw">let </span>elements = classes.elements(<span class="number">3</span>).collect::&lt;Vec&lt;<span class="kw">_</span>&gt;&gt;();
<a href=#374 id=374 data-nosnippet>374</a> <span class="macro">assert_eq!</span>(elements, <span class="macro">vec!</span>[<span class="string">b'g'</span>, <span class="string">b'h'</span>, <span class="string">b'i'</span>, <span class="string">b'j'</span>, <span class="string">b'k'</span>, <span class="string">b'l'</span>, <span class="string">b'm'</span>,],);
<a href=#375 id=375 data-nosnippet>375</a>
<a href=#376 id=376 data-nosnippet>376</a> <span class="kw">let </span>elements = classes.elements(<span class="number">4</span>).collect::&lt;Vec&lt;<span class="kw">_</span>&gt;&gt;();
<a href=#377 id=377 data-nosnippet>377</a> <span class="macro">assert_eq!</span>(elements.len(), <span class="number">12</span>);
<a href=#378 id=378 data-nosnippet>378</a> <span class="macro">assert_eq!</span>(elements[<span class="number">0</span>], <span class="string">b'n'</span>);
<a href=#379 id=379 data-nosnippet>379</a> <span class="macro">assert_eq!</span>(elements[<span class="number">11</span>], <span class="string">b'y'</span>);
<a href=#380 id=380 data-nosnippet>380</a>
<a href=#381 id=381 data-nosnippet>381</a> <span class="kw">let </span>elements = classes.elements(<span class="number">5</span>).collect::&lt;Vec&lt;<span class="kw">_</span>&gt;&gt;();
<a href=#382 id=382 data-nosnippet>382</a> <span class="macro">assert_eq!</span>(elements, <span class="macro">vec!</span>[<span class="string">b'z'</span>]);
<a href=#383 id=383 data-nosnippet>383</a>
<a href=#384 id=384 data-nosnippet>384</a> <span class="kw">let </span>elements = classes.elements(<span class="number">6</span>).collect::&lt;Vec&lt;<span class="kw">_</span>&gt;&gt;();
<a href=#385 id=385 data-nosnippet>385</a> <span class="macro">assert_eq!</span>(elements.len(), <span class="number">133</span>);
<a href=#386 id=386 data-nosnippet>386</a> <span class="macro">assert_eq!</span>(elements[<span class="number">0</span>], <span class="string">b'\x7B'</span>);
<a href=#387 id=387 data-nosnippet>387</a> <span class="macro">assert_eq!</span>(elements[<span class="number">132</span>], <span class="string">b'\xFF'</span>);
<a href=#388 id=388 data-nosnippet>388</a> }
<a href=#389 id=389 data-nosnippet>389</a>
<a href=#390 id=390 data-nosnippet>390</a> <span class="attr">#[test]
<a href=#391 id=391 data-nosnippet>391</a> </span><span class="kw">fn </span>elements_singletons() {
<a href=#392 id=392 data-nosnippet>392</a> <span class="kw">let </span>classes = ByteClasses::singletons();
<a href=#393 id=393 data-nosnippet>393</a> <span class="macro">assert_eq!</span>(classes.alphabet_len(), <span class="number">256</span>);
<a href=#394 id=394 data-nosnippet>394</a>
<a href=#395 id=395 data-nosnippet>395</a> <span class="kw">let </span>elements = classes.elements(<span class="string">b'a'</span>).collect::&lt;Vec&lt;<span class="kw">_</span>&gt;&gt;();
<a href=#396 id=396 data-nosnippet>396</a> <span class="macro">assert_eq!</span>(elements, <span class="macro">vec!</span>[<span class="string">b'a'</span>]);
<a href=#397 id=397 data-nosnippet>397</a> }
<a href=#398 id=398 data-nosnippet>398</a>
<a href=#399 id=399 data-nosnippet>399</a> <span class="attr">#[test]
<a href=#400 id=400 data-nosnippet>400</a> </span><span class="kw">fn </span>elements_empty() {
<a href=#401 id=401 data-nosnippet>401</a> <span class="kw">let </span>classes = ByteClasses::empty();
<a href=#402 id=402 data-nosnippet>402</a> <span class="macro">assert_eq!</span>(classes.alphabet_len(), <span class="number">1</span>);
<a href=#403 id=403 data-nosnippet>403</a>
<a href=#404 id=404 data-nosnippet>404</a> <span class="kw">let </span>elements = classes.elements(<span class="number">0</span>).collect::&lt;Vec&lt;<span class="kw">_</span>&gt;&gt;();
<a href=#405 id=405 data-nosnippet>405</a> <span class="macro">assert_eq!</span>(elements.len(), <span class="number">256</span>);
<a href=#406 id=406 data-nosnippet>406</a> <span class="macro">assert_eq!</span>(elements[<span class="number">0</span>], <span class="string">b'\x00'</span>);
<a href=#407 id=407 data-nosnippet>407</a> <span class="macro">assert_eq!</span>(elements[<span class="number">255</span>], <span class="string">b'\xFF'</span>);
<a href=#408 id=408 data-nosnippet>408</a> }
<a href=#409 id=409 data-nosnippet>409</a>}
</code></pre></div></section></main></body></html>

View File

@@ -0,0 +1,125 @@
<!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 `/home/newkirk/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/aho-corasick-1.1.4/src/util/buffer.rs`."><title>buffer.rs - source</title><script>if(window.location.protocol!=="file:")document.head.insertAdjacentHTML("beforeend","SourceSerif4-Regular-6b053e98.ttf.woff2,FiraSans-Italic-81dc35de.woff2,FiraSans-Regular-0fe48ade.woff2,FiraSans-MediumItalic-ccf7e434.woff2,FiraSans-Medium-e1aa3f0a.woff2,SourceCodePro-Regular-8badfe75.ttf.woff2,SourceCodePro-Semibold-aa29a496.ttf.woff2".split(",").map(f=>`<link rel="preload" as="font" type="font/woff2"href="../../../static.files/${f}">`).join(""))</script><link rel="stylesheet" href="../../../static.files/normalize-9960930a.css"><link rel="stylesheet" href="../../../static.files/rustdoc-ca0dd0c4.css"><meta name="rustdoc-vars" data-root-path="../../../" data-static-root-path="../../../static.files/" data-current-crate="aho_corasick" data-themes="" data-resource-suffix="" data-rustdoc-version="1.93.1 (01f6ddf75 2026-02-11) (Arch Linux rust 1:1.93.1-1)" data-channel="1.93.1" data-search-js="search-9e2438ea.js" data-stringdex-js="stringdex-a3946164.js" data-settings-js="settings-c38705f0.js" ><script src="../../../static.files/storage-e2aeef58.js"></script><script defer src="../../../static.files/src-script-813739b1.js"></script><script defer src="../../../src-files.js"></script><script defer src="../../../static.files/main-a410ff4d.js"></script><noscript><link rel="stylesheet" href="../../../static.files/noscript-263c88ec.css"></noscript><link rel="alternate icon" type="image/png" href="../../../static.files/favicon-32x32-eab170b8.png"><link rel="icon" type="image/svg+xml" href="../../../static.files/favicon-044be391.svg"></head><body class="rustdoc src"><!--[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="src-sidebar-title"><h2>Files</h2></div></nav><div class="sidebar-resizer" title="Drag to resize sidebar"></div><main><section id="main-content" class="content"><div class="main-heading"><h1><div class="sub-heading">aho_corasick/util/</div>buffer.rs</h1><rustdoc-toolbar></rustdoc-toolbar></div><div class="example-wrap digits-3"><pre class="rust"><code><a href=#1 id=1 data-nosnippet>1</a><span class="kw">use </span>alloc::{vec, vec::Vec};
<a href=#2 id=2 data-nosnippet>2</a>
<a href=#3 id=3 data-nosnippet>3</a><span class="doccomment">/// The default buffer capacity that we use for the stream buffer.
<a href=#4 id=4 data-nosnippet>4</a></span><span class="kw">const </span>DEFAULT_BUFFER_CAPACITY: usize = <span class="number">64 </span>* (<span class="number">1 </span>&lt;&lt; <span class="number">10</span>); <span class="comment">// 64 KB
<a href=#5 id=5 data-nosnippet>5</a>
<a href=#6 id=6 data-nosnippet>6</a></span><span class="doccomment">/// A fairly simple roll buffer for supporting stream searches.
<a href=#7 id=7 data-nosnippet>7</a>///
<a href=#8 id=8 data-nosnippet>8</a>/// This buffer acts as a temporary place to store a fixed amount of data when
<a href=#9 id=9 data-nosnippet>9</a>/// reading from a stream. Its central purpose is to allow "rolling" some
<a href=#10 id=10 data-nosnippet>10</a>/// suffix of the data to the beginning of the buffer before refilling it with
<a href=#11 id=11 data-nosnippet>11</a>/// more data from the stream. For example, let's say we are trying to match
<a href=#12 id=12 data-nosnippet>12</a>/// "foobar" on a stream. When we report the match, we'd like to not only
<a href=#13 id=13 data-nosnippet>13</a>/// report the correct offsets at which the match occurs, but also the matching
<a href=#14 id=14 data-nosnippet>14</a>/// bytes themselves. So let's say our stream is a file with the following
<a href=#15 id=15 data-nosnippet>15</a>/// contents: `test test foobar test test`. Now assume that we happen to read
<a href=#16 id=16 data-nosnippet>16</a>/// the aforementioned file in two chunks: `test test foo` and `bar test test`.
<a href=#17 id=17 data-nosnippet>17</a>/// Naively, it would not be possible to report a single contiguous `foobar`
<a href=#18 id=18 data-nosnippet>18</a>/// match, but this roll buffer allows us to do that. Namely, after the second
<a href=#19 id=19 data-nosnippet>19</a>/// read, the contents of the buffer should be `st foobar test test`, where the
<a href=#20 id=20 data-nosnippet>20</a>/// search should ultimately resume immediately after `foo`. (The prefix `st `
<a href=#21 id=21 data-nosnippet>21</a>/// is included because the roll buffer saves N bytes at the end of the buffer,
<a href=#22 id=22 data-nosnippet>22</a>/// where N is the maximum possible length of a match.)
<a href=#23 id=23 data-nosnippet>23</a>///
<a href=#24 id=24 data-nosnippet>24</a>/// A lot of the logic for dealing with this is unfortunately split out between
<a href=#25 id=25 data-nosnippet>25</a>/// this roll buffer and the `StreamChunkIter`.
<a href=#26 id=26 data-nosnippet>26</a>///
<a href=#27 id=27 data-nosnippet>27</a>/// Note also that this buffer is not actually required to just report matches.
<a href=#28 id=28 data-nosnippet>28</a>/// Because a `Match` is just some offsets. But it *is* required for supporting
<a href=#29 id=29 data-nosnippet>29</a>/// things like `try_stream_replace_all` because that needs some mechanism for
<a href=#30 id=30 data-nosnippet>30</a>/// knowing which bytes in the stream correspond to a match and which don't. So
<a href=#31 id=31 data-nosnippet>31</a>/// when a match occurs across two `read` calls, *something* needs to retain
<a href=#32 id=32 data-nosnippet>32</a>/// the bytes from the previous `read` call because you don't know before the
<a href=#33 id=33 data-nosnippet>33</a>/// second read call whether a match exists or not.
<a href=#34 id=34 data-nosnippet>34</a></span><span class="attr">#[derive(Debug)]
<a href=#35 id=35 data-nosnippet>35</a></span><span class="kw">pub</span>(<span class="kw">crate</span>) <span class="kw">struct </span>Buffer {
<a href=#36 id=36 data-nosnippet>36</a> <span class="doccomment">/// The raw buffer contents. This has a fixed size and never increases.
<a href=#37 id=37 data-nosnippet>37</a> </span>buf: Vec&lt;u8&gt;,
<a href=#38 id=38 data-nosnippet>38</a> <span class="doccomment">/// The minimum size of the buffer, which is equivalent to the maximum
<a href=#39 id=39 data-nosnippet>39</a> /// possible length of a match. This corresponds to the amount that we
<a href=#40 id=40 data-nosnippet>40</a> /// roll
<a href=#41 id=41 data-nosnippet>41</a> </span>min: usize,
<a href=#42 id=42 data-nosnippet>42</a> <span class="doccomment">/// The end of the contents of this buffer.
<a href=#43 id=43 data-nosnippet>43</a> </span>end: usize,
<a href=#44 id=44 data-nosnippet>44</a>}
<a href=#45 id=45 data-nosnippet>45</a>
<a href=#46 id=46 data-nosnippet>46</a><span class="kw">impl </span>Buffer {
<a href=#47 id=47 data-nosnippet>47</a> <span class="doccomment">/// Create a new buffer for stream searching. The minimum buffer length
<a href=#48 id=48 data-nosnippet>48</a> /// given should be the size of the maximum possible match length.
<a href=#49 id=49 data-nosnippet>49</a> </span><span class="kw">pub</span>(<span class="kw">crate</span>) <span class="kw">fn </span>new(min_buffer_len: usize) -&gt; Buffer {
<a href=#50 id=50 data-nosnippet>50</a> <span class="kw">let </span>min = core::cmp::max(<span class="number">1</span>, min_buffer_len);
<a href=#51 id=51 data-nosnippet>51</a> <span class="comment">// The minimum buffer amount is also the amount that we roll our
<a href=#52 id=52 data-nosnippet>52</a> // buffer in order to support incremental searching. To this end,
<a href=#53 id=53 data-nosnippet>53</a> // our actual capacity needs to be at least 1 byte bigger than our
<a href=#54 id=54 data-nosnippet>54</a> // minimum amount, otherwise we won't have any overlap. In actuality,
<a href=#55 id=55 data-nosnippet>55</a> // we want our buffer to be a bit bigger than that for performance
<a href=#56 id=56 data-nosnippet>56</a> // reasons, so we set a lower bound of `8 * min`.
<a href=#57 id=57 data-nosnippet>57</a> //
<a href=#58 id=58 data-nosnippet>58</a> // TODO: It would be good to find a way to test the streaming
<a href=#59 id=59 data-nosnippet>59</a> // implementation with the minimal buffer size. For now, we just
<a href=#60 id=60 data-nosnippet>60</a> // uncomment out the next line and comment out the subsequent line.
<a href=#61 id=61 data-nosnippet>61</a> // let capacity = 1 + min;
<a href=#62 id=62 data-nosnippet>62</a> </span><span class="kw">let </span>capacity = core::cmp::max(min * <span class="number">8</span>, DEFAULT_BUFFER_CAPACITY);
<a href=#63 id=63 data-nosnippet>63</a> Buffer { buf: <span class="macro">vec!</span>[<span class="number">0</span>; capacity], min, end: <span class="number">0 </span>}
<a href=#64 id=64 data-nosnippet>64</a> }
<a href=#65 id=65 data-nosnippet>65</a>
<a href=#66 id=66 data-nosnippet>66</a> <span class="doccomment">/// Return the contents of this buffer.
<a href=#67 id=67 data-nosnippet>67</a> </span><span class="attr">#[inline]
<a href=#68 id=68 data-nosnippet>68</a> </span><span class="kw">pub</span>(<span class="kw">crate</span>) <span class="kw">fn </span>buffer(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; <span class="kw-2">&amp;</span>[u8] {
<a href=#69 id=69 data-nosnippet>69</a> <span class="kw-2">&amp;</span><span class="self">self</span>.buf[..<span class="self">self</span>.end]
<a href=#70 id=70 data-nosnippet>70</a> }
<a href=#71 id=71 data-nosnippet>71</a>
<a href=#72 id=72 data-nosnippet>72</a> <span class="doccomment">/// Return the minimum size of the buffer. The only way a buffer may be
<a href=#73 id=73 data-nosnippet>73</a> /// smaller than this is if the stream itself contains less than the
<a href=#74 id=74 data-nosnippet>74</a> /// minimum buffer amount.
<a href=#75 id=75 data-nosnippet>75</a> </span><span class="attr">#[inline]
<a href=#76 id=76 data-nosnippet>76</a> </span><span class="kw">pub</span>(<span class="kw">crate</span>) <span class="kw">fn </span>min_buffer_len(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; usize {
<a href=#77 id=77 data-nosnippet>77</a> <span class="self">self</span>.min
<a href=#78 id=78 data-nosnippet>78</a> }
<a href=#79 id=79 data-nosnippet>79</a>
<a href=#80 id=80 data-nosnippet>80</a> <span class="doccomment">/// Return all free capacity in this buffer.
<a href=#81 id=81 data-nosnippet>81</a> </span><span class="kw">fn </span>free_buffer(<span class="kw-2">&amp;mut </span><span class="self">self</span>) -&gt; <span class="kw-2">&amp;mut </span>[u8] {
<a href=#82 id=82 data-nosnippet>82</a> <span class="kw-2">&amp;mut </span><span class="self">self</span>.buf[<span class="self">self</span>.end..]
<a href=#83 id=83 data-nosnippet>83</a> }
<a href=#84 id=84 data-nosnippet>84</a>
<a href=#85 id=85 data-nosnippet>85</a> <span class="doccomment">/// Refill the contents of this buffer by reading as much as possible into
<a href=#86 id=86 data-nosnippet>86</a> /// this buffer's free capacity. If no more bytes could be read, then this
<a href=#87 id=87 data-nosnippet>87</a> /// returns false. Otherwise, this reads until it has filled the buffer
<a href=#88 id=88 data-nosnippet>88</a> /// past the minimum amount.
<a href=#89 id=89 data-nosnippet>89</a> </span><span class="kw">pub</span>(<span class="kw">crate</span>) <span class="kw">fn </span>fill&lt;R: std::io::Read&gt;(
<a href=#90 id=90 data-nosnippet>90</a> <span class="kw-2">&amp;mut </span><span class="self">self</span>,
<a href=#91 id=91 data-nosnippet>91</a> <span class="kw-2">mut </span>rdr: R,
<a href=#92 id=92 data-nosnippet>92</a> ) -&gt; std::io::Result&lt;bool&gt; {
<a href=#93 id=93 data-nosnippet>93</a> <span class="kw">let </span><span class="kw-2">mut </span>readany = <span class="bool-val">false</span>;
<a href=#94 id=94 data-nosnippet>94</a> <span class="kw">loop </span>{
<a href=#95 id=95 data-nosnippet>95</a> <span class="kw">let </span>readlen = rdr.read(<span class="self">self</span>.free_buffer())<span class="question-mark">?</span>;
<a href=#96 id=96 data-nosnippet>96</a> <span class="kw">if </span>readlen == <span class="number">0 </span>{
<a href=#97 id=97 data-nosnippet>97</a> <span class="kw">return </span><span class="prelude-val">Ok</span>(readany);
<a href=#98 id=98 data-nosnippet>98</a> }
<a href=#99 id=99 data-nosnippet>99</a> readany = <span class="bool-val">true</span>;
<a href=#100 id=100 data-nosnippet>100</a> <span class="self">self</span>.end += readlen;
<a href=#101 id=101 data-nosnippet>101</a> <span class="kw">if </span><span class="self">self</span>.buffer().len() &gt;= <span class="self">self</span>.min {
<a href=#102 id=102 data-nosnippet>102</a> <span class="kw">return </span><span class="prelude-val">Ok</span>(<span class="bool-val">true</span>);
<a href=#103 id=103 data-nosnippet>103</a> }
<a href=#104 id=104 data-nosnippet>104</a> }
<a href=#105 id=105 data-nosnippet>105</a> }
<a href=#106 id=106 data-nosnippet>106</a>
<a href=#107 id=107 data-nosnippet>107</a> <span class="doccomment">/// Roll the contents of the buffer so that the suffix of this buffer is
<a href=#108 id=108 data-nosnippet>108</a> /// moved to the front and all other contents are dropped. The size of the
<a href=#109 id=109 data-nosnippet>109</a> /// suffix corresponds precisely to the minimum buffer length.
<a href=#110 id=110 data-nosnippet>110</a> ///
<a href=#111 id=111 data-nosnippet>111</a> /// This should only be called when the entire contents of this buffer have
<a href=#112 id=112 data-nosnippet>112</a> /// been searched.
<a href=#113 id=113 data-nosnippet>113</a> </span><span class="kw">pub</span>(<span class="kw">crate</span>) <span class="kw">fn </span>roll(<span class="kw-2">&amp;mut </span><span class="self">self</span>) {
<a href=#114 id=114 data-nosnippet>114</a> <span class="kw">let </span>roll_start = <span class="self">self
<a href=#115 id=115 data-nosnippet>115</a> </span>.end
<a href=#116 id=116 data-nosnippet>116</a> .checked_sub(<span class="self">self</span>.min)
<a href=#117 id=117 data-nosnippet>117</a> .expect(<span class="string">"buffer capacity should be bigger than minimum amount"</span>);
<a href=#118 id=118 data-nosnippet>118</a> <span class="kw">let </span>roll_end = roll_start + <span class="self">self</span>.min;
<a href=#119 id=119 data-nosnippet>119</a>
<a href=#120 id=120 data-nosnippet>120</a> <span class="macro">assert!</span>(roll_end &lt;= <span class="self">self</span>.end);
<a href=#121 id=121 data-nosnippet>121</a> <span class="self">self</span>.buf.copy_within(roll_start..roll_end, <span class="number">0</span>);
<a href=#122 id=122 data-nosnippet>122</a> <span class="self">self</span>.end = <span class="self">self</span>.min;
<a href=#123 id=123 data-nosnippet>123</a> }
<a href=#124 id=124 data-nosnippet>124</a>}
</code></pre></div></section></main></body></html>

View File

@@ -0,0 +1,259 @@
<!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 `/home/newkirk/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/aho-corasick-1.1.4/src/util/byte_frequencies.rs`."><title>byte_frequencies.rs - source</title><script>if(window.location.protocol!=="file:")document.head.insertAdjacentHTML("beforeend","SourceSerif4-Regular-6b053e98.ttf.woff2,FiraSans-Italic-81dc35de.woff2,FiraSans-Regular-0fe48ade.woff2,FiraSans-MediumItalic-ccf7e434.woff2,FiraSans-Medium-e1aa3f0a.woff2,SourceCodePro-Regular-8badfe75.ttf.woff2,SourceCodePro-Semibold-aa29a496.ttf.woff2".split(",").map(f=>`<link rel="preload" as="font" type="font/woff2"href="../../../static.files/${f}">`).join(""))</script><link rel="stylesheet" href="../../../static.files/normalize-9960930a.css"><link rel="stylesheet" href="../../../static.files/rustdoc-ca0dd0c4.css"><meta name="rustdoc-vars" data-root-path="../../../" data-static-root-path="../../../static.files/" data-current-crate="aho_corasick" data-themes="" data-resource-suffix="" data-rustdoc-version="1.93.1 (01f6ddf75 2026-02-11) (Arch Linux rust 1:1.93.1-1)" data-channel="1.93.1" data-search-js="search-9e2438ea.js" data-stringdex-js="stringdex-a3946164.js" data-settings-js="settings-c38705f0.js" ><script src="../../../static.files/storage-e2aeef58.js"></script><script defer src="../../../static.files/src-script-813739b1.js"></script><script defer src="../../../src-files.js"></script><script defer src="../../../static.files/main-a410ff4d.js"></script><noscript><link rel="stylesheet" href="../../../static.files/noscript-263c88ec.css"></noscript><link rel="alternate icon" type="image/png" href="../../../static.files/favicon-32x32-eab170b8.png"><link rel="icon" type="image/svg+xml" href="../../../static.files/favicon-044be391.svg"></head><body class="rustdoc src"><!--[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="src-sidebar-title"><h2>Files</h2></div></nav><div class="sidebar-resizer" title="Drag to resize sidebar"></div><main><section id="main-content" class="content"><div class="main-heading"><h1><div class="sub-heading">aho_corasick/util/</div>byte_frequencies.rs</h1><rustdoc-toolbar></rustdoc-toolbar></div><div class="example-wrap digits-3"><pre class="rust"><code><a href=#1 id=1 data-nosnippet>1</a><span class="kw">pub const </span>BYTE_FREQUENCIES: [u8; <span class="number">256</span>] = [
<a href=#2 id=2 data-nosnippet>2</a> <span class="number">55</span>, <span class="comment">// '\x00'
<a href=#3 id=3 data-nosnippet>3</a> </span><span class="number">52</span>, <span class="comment">// '\x01'
<a href=#4 id=4 data-nosnippet>4</a> </span><span class="number">51</span>, <span class="comment">// '\x02'
<a href=#5 id=5 data-nosnippet>5</a> </span><span class="number">50</span>, <span class="comment">// '\x03'
<a href=#6 id=6 data-nosnippet>6</a> </span><span class="number">49</span>, <span class="comment">// '\x04'
<a href=#7 id=7 data-nosnippet>7</a> </span><span class="number">48</span>, <span class="comment">// '\x05'
<a href=#8 id=8 data-nosnippet>8</a> </span><span class="number">47</span>, <span class="comment">// '\x06'
<a href=#9 id=9 data-nosnippet>9</a> </span><span class="number">46</span>, <span class="comment">// '\x07'
<a href=#10 id=10 data-nosnippet>10</a> </span><span class="number">45</span>, <span class="comment">// '\x08'
<a href=#11 id=11 data-nosnippet>11</a> </span><span class="number">103</span>, <span class="comment">// '\t'
<a href=#12 id=12 data-nosnippet>12</a> </span><span class="number">242</span>, <span class="comment">// '\n'
<a href=#13 id=13 data-nosnippet>13</a> </span><span class="number">66</span>, <span class="comment">// '\x0b'
<a href=#14 id=14 data-nosnippet>14</a> </span><span class="number">67</span>, <span class="comment">// '\x0c'
<a href=#15 id=15 data-nosnippet>15</a> </span><span class="number">229</span>, <span class="comment">// '\r'
<a href=#16 id=16 data-nosnippet>16</a> </span><span class="number">44</span>, <span class="comment">// '\x0e'
<a href=#17 id=17 data-nosnippet>17</a> </span><span class="number">43</span>, <span class="comment">// '\x0f'
<a href=#18 id=18 data-nosnippet>18</a> </span><span class="number">42</span>, <span class="comment">// '\x10'
<a href=#19 id=19 data-nosnippet>19</a> </span><span class="number">41</span>, <span class="comment">// '\x11'
<a href=#20 id=20 data-nosnippet>20</a> </span><span class="number">40</span>, <span class="comment">// '\x12'
<a href=#21 id=21 data-nosnippet>21</a> </span><span class="number">39</span>, <span class="comment">// '\x13'
<a href=#22 id=22 data-nosnippet>22</a> </span><span class="number">38</span>, <span class="comment">// '\x14'
<a href=#23 id=23 data-nosnippet>23</a> </span><span class="number">37</span>, <span class="comment">// '\x15'
<a href=#24 id=24 data-nosnippet>24</a> </span><span class="number">36</span>, <span class="comment">// '\x16'
<a href=#25 id=25 data-nosnippet>25</a> </span><span class="number">35</span>, <span class="comment">// '\x17'
<a href=#26 id=26 data-nosnippet>26</a> </span><span class="number">34</span>, <span class="comment">// '\x18'
<a href=#27 id=27 data-nosnippet>27</a> </span><span class="number">33</span>, <span class="comment">// '\x19'
<a href=#28 id=28 data-nosnippet>28</a> </span><span class="number">56</span>, <span class="comment">// '\x1a'
<a href=#29 id=29 data-nosnippet>29</a> </span><span class="number">32</span>, <span class="comment">// '\x1b'
<a href=#30 id=30 data-nosnippet>30</a> </span><span class="number">31</span>, <span class="comment">// '\x1c'
<a href=#31 id=31 data-nosnippet>31</a> </span><span class="number">30</span>, <span class="comment">// '\x1d'
<a href=#32 id=32 data-nosnippet>32</a> </span><span class="number">29</span>, <span class="comment">// '\x1e'
<a href=#33 id=33 data-nosnippet>33</a> </span><span class="number">28</span>, <span class="comment">// '\x1f'
<a href=#34 id=34 data-nosnippet>34</a> </span><span class="number">255</span>, <span class="comment">// ' '
<a href=#35 id=35 data-nosnippet>35</a> </span><span class="number">148</span>, <span class="comment">// '!'
<a href=#36 id=36 data-nosnippet>36</a> </span><span class="number">164</span>, <span class="comment">// '"'
<a href=#37 id=37 data-nosnippet>37</a> </span><span class="number">149</span>, <span class="comment">// '#'
<a href=#38 id=38 data-nosnippet>38</a> </span><span class="number">136</span>, <span class="comment">// '$'
<a href=#39 id=39 data-nosnippet>39</a> </span><span class="number">160</span>, <span class="comment">// '%'
<a href=#40 id=40 data-nosnippet>40</a> </span><span class="number">155</span>, <span class="comment">// '&amp;'
<a href=#41 id=41 data-nosnippet>41</a> </span><span class="number">173</span>, <span class="comment">// "'"
<a href=#42 id=42 data-nosnippet>42</a> </span><span class="number">221</span>, <span class="comment">// '('
<a href=#43 id=43 data-nosnippet>43</a> </span><span class="number">222</span>, <span class="comment">// ')'
<a href=#44 id=44 data-nosnippet>44</a> </span><span class="number">134</span>, <span class="comment">// '*'
<a href=#45 id=45 data-nosnippet>45</a> </span><span class="number">122</span>, <span class="comment">// '+'
<a href=#46 id=46 data-nosnippet>46</a> </span><span class="number">232</span>, <span class="comment">// ','
<a href=#47 id=47 data-nosnippet>47</a> </span><span class="number">202</span>, <span class="comment">// '-'
<a href=#48 id=48 data-nosnippet>48</a> </span><span class="number">215</span>, <span class="comment">// '.'
<a href=#49 id=49 data-nosnippet>49</a> </span><span class="number">224</span>, <span class="comment">// '/'
<a href=#50 id=50 data-nosnippet>50</a> </span><span class="number">208</span>, <span class="comment">// '0'
<a href=#51 id=51 data-nosnippet>51</a> </span><span class="number">220</span>, <span class="comment">// '1'
<a href=#52 id=52 data-nosnippet>52</a> </span><span class="number">204</span>, <span class="comment">// '2'
<a href=#53 id=53 data-nosnippet>53</a> </span><span class="number">187</span>, <span class="comment">// '3'
<a href=#54 id=54 data-nosnippet>54</a> </span><span class="number">183</span>, <span class="comment">// '4'
<a href=#55 id=55 data-nosnippet>55</a> </span><span class="number">179</span>, <span class="comment">// '5'
<a href=#56 id=56 data-nosnippet>56</a> </span><span class="number">177</span>, <span class="comment">// '6'
<a href=#57 id=57 data-nosnippet>57</a> </span><span class="number">168</span>, <span class="comment">// '7'
<a href=#58 id=58 data-nosnippet>58</a> </span><span class="number">178</span>, <span class="comment">// '8'
<a href=#59 id=59 data-nosnippet>59</a> </span><span class="number">200</span>, <span class="comment">// '9'
<a href=#60 id=60 data-nosnippet>60</a> </span><span class="number">226</span>, <span class="comment">// ':'
<a href=#61 id=61 data-nosnippet>61</a> </span><span class="number">195</span>, <span class="comment">// ';'
<a href=#62 id=62 data-nosnippet>62</a> </span><span class="number">154</span>, <span class="comment">// '&lt;'
<a href=#63 id=63 data-nosnippet>63</a> </span><span class="number">184</span>, <span class="comment">// '='
<a href=#64 id=64 data-nosnippet>64</a> </span><span class="number">174</span>, <span class="comment">// '&gt;'
<a href=#65 id=65 data-nosnippet>65</a> </span><span class="number">126</span>, <span class="comment">// '?'
<a href=#66 id=66 data-nosnippet>66</a> </span><span class="number">120</span>, <span class="comment">// '@'
<a href=#67 id=67 data-nosnippet>67</a> </span><span class="number">191</span>, <span class="comment">// 'A'
<a href=#68 id=68 data-nosnippet>68</a> </span><span class="number">157</span>, <span class="comment">// 'B'
<a href=#69 id=69 data-nosnippet>69</a> </span><span class="number">194</span>, <span class="comment">// 'C'
<a href=#70 id=70 data-nosnippet>70</a> </span><span class="number">170</span>, <span class="comment">// 'D'
<a href=#71 id=71 data-nosnippet>71</a> </span><span class="number">189</span>, <span class="comment">// 'E'
<a href=#72 id=72 data-nosnippet>72</a> </span><span class="number">162</span>, <span class="comment">// 'F'
<a href=#73 id=73 data-nosnippet>73</a> </span><span class="number">161</span>, <span class="comment">// 'G'
<a href=#74 id=74 data-nosnippet>74</a> </span><span class="number">150</span>, <span class="comment">// 'H'
<a href=#75 id=75 data-nosnippet>75</a> </span><span class="number">193</span>, <span class="comment">// 'I'
<a href=#76 id=76 data-nosnippet>76</a> </span><span class="number">142</span>, <span class="comment">// 'J'
<a href=#77 id=77 data-nosnippet>77</a> </span><span class="number">137</span>, <span class="comment">// 'K'
<a href=#78 id=78 data-nosnippet>78</a> </span><span class="number">171</span>, <span class="comment">// 'L'
<a href=#79 id=79 data-nosnippet>79</a> </span><span class="number">176</span>, <span class="comment">// 'M'
<a href=#80 id=80 data-nosnippet>80</a> </span><span class="number">185</span>, <span class="comment">// 'N'
<a href=#81 id=81 data-nosnippet>81</a> </span><span class="number">167</span>, <span class="comment">// 'O'
<a href=#82 id=82 data-nosnippet>82</a> </span><span class="number">186</span>, <span class="comment">// 'P'
<a href=#83 id=83 data-nosnippet>83</a> </span><span class="number">112</span>, <span class="comment">// 'Q'
<a href=#84 id=84 data-nosnippet>84</a> </span><span class="number">175</span>, <span class="comment">// 'R'
<a href=#85 id=85 data-nosnippet>85</a> </span><span class="number">192</span>, <span class="comment">// 'S'
<a href=#86 id=86 data-nosnippet>86</a> </span><span class="number">188</span>, <span class="comment">// 'T'
<a href=#87 id=87 data-nosnippet>87</a> </span><span class="number">156</span>, <span class="comment">// 'U'
<a href=#88 id=88 data-nosnippet>88</a> </span><span class="number">140</span>, <span class="comment">// 'V'
<a href=#89 id=89 data-nosnippet>89</a> </span><span class="number">143</span>, <span class="comment">// 'W'
<a href=#90 id=90 data-nosnippet>90</a> </span><span class="number">123</span>, <span class="comment">// 'X'
<a href=#91 id=91 data-nosnippet>91</a> </span><span class="number">133</span>, <span class="comment">// 'Y'
<a href=#92 id=92 data-nosnippet>92</a> </span><span class="number">128</span>, <span class="comment">// 'Z'
<a href=#93 id=93 data-nosnippet>93</a> </span><span class="number">147</span>, <span class="comment">// '['
<a href=#94 id=94 data-nosnippet>94</a> </span><span class="number">138</span>, <span class="comment">// '\\'
<a href=#95 id=95 data-nosnippet>95</a> </span><span class="number">146</span>, <span class="comment">// ']'
<a href=#96 id=96 data-nosnippet>96</a> </span><span class="number">114</span>, <span class="comment">// '^'
<a href=#97 id=97 data-nosnippet>97</a> </span><span class="number">223</span>, <span class="comment">// '_'
<a href=#98 id=98 data-nosnippet>98</a> </span><span class="number">151</span>, <span class="comment">// '`'
<a href=#99 id=99 data-nosnippet>99</a> </span><span class="number">249</span>, <span class="comment">// 'a'
<a href=#100 id=100 data-nosnippet>100</a> </span><span class="number">216</span>, <span class="comment">// 'b'
<a href=#101 id=101 data-nosnippet>101</a> </span><span class="number">238</span>, <span class="comment">// 'c'
<a href=#102 id=102 data-nosnippet>102</a> </span><span class="number">236</span>, <span class="comment">// 'd'
<a href=#103 id=103 data-nosnippet>103</a> </span><span class="number">253</span>, <span class="comment">// 'e'
<a href=#104 id=104 data-nosnippet>104</a> </span><span class="number">227</span>, <span class="comment">// 'f'
<a href=#105 id=105 data-nosnippet>105</a> </span><span class="number">218</span>, <span class="comment">// 'g'
<a href=#106 id=106 data-nosnippet>106</a> </span><span class="number">230</span>, <span class="comment">// 'h'
<a href=#107 id=107 data-nosnippet>107</a> </span><span class="number">247</span>, <span class="comment">// 'i'
<a href=#108 id=108 data-nosnippet>108</a> </span><span class="number">135</span>, <span class="comment">// 'j'
<a href=#109 id=109 data-nosnippet>109</a> </span><span class="number">180</span>, <span class="comment">// 'k'
<a href=#110 id=110 data-nosnippet>110</a> </span><span class="number">241</span>, <span class="comment">// 'l'
<a href=#111 id=111 data-nosnippet>111</a> </span><span class="number">233</span>, <span class="comment">// 'm'
<a href=#112 id=112 data-nosnippet>112</a> </span><span class="number">246</span>, <span class="comment">// 'n'
<a href=#113 id=113 data-nosnippet>113</a> </span><span class="number">244</span>, <span class="comment">// 'o'
<a href=#114 id=114 data-nosnippet>114</a> </span><span class="number">231</span>, <span class="comment">// 'p'
<a href=#115 id=115 data-nosnippet>115</a> </span><span class="number">139</span>, <span class="comment">// 'q'
<a href=#116 id=116 data-nosnippet>116</a> </span><span class="number">245</span>, <span class="comment">// 'r'
<a href=#117 id=117 data-nosnippet>117</a> </span><span class="number">243</span>, <span class="comment">// 's'
<a href=#118 id=118 data-nosnippet>118</a> </span><span class="number">251</span>, <span class="comment">// 't'
<a href=#119 id=119 data-nosnippet>119</a> </span><span class="number">235</span>, <span class="comment">// 'u'
<a href=#120 id=120 data-nosnippet>120</a> </span><span class="number">201</span>, <span class="comment">// 'v'
<a href=#121 id=121 data-nosnippet>121</a> </span><span class="number">196</span>, <span class="comment">// 'w'
<a href=#122 id=122 data-nosnippet>122</a> </span><span class="number">240</span>, <span class="comment">// 'x'
<a href=#123 id=123 data-nosnippet>123</a> </span><span class="number">214</span>, <span class="comment">// 'y'
<a href=#124 id=124 data-nosnippet>124</a> </span><span class="number">152</span>, <span class="comment">// 'z'
<a href=#125 id=125 data-nosnippet>125</a> </span><span class="number">182</span>, <span class="comment">// '{'
<a href=#126 id=126 data-nosnippet>126</a> </span><span class="number">205</span>, <span class="comment">// '|'
<a href=#127 id=127 data-nosnippet>127</a> </span><span class="number">181</span>, <span class="comment">// '}'
<a href=#128 id=128 data-nosnippet>128</a> </span><span class="number">127</span>, <span class="comment">// '~'
<a href=#129 id=129 data-nosnippet>129</a> </span><span class="number">27</span>, <span class="comment">// '\x7f'
<a href=#130 id=130 data-nosnippet>130</a> </span><span class="number">212</span>, <span class="comment">// '\x80'
<a href=#131 id=131 data-nosnippet>131</a> </span><span class="number">211</span>, <span class="comment">// '\x81'
<a href=#132 id=132 data-nosnippet>132</a> </span><span class="number">210</span>, <span class="comment">// '\x82'
<a href=#133 id=133 data-nosnippet>133</a> </span><span class="number">213</span>, <span class="comment">// '\x83'
<a href=#134 id=134 data-nosnippet>134</a> </span><span class="number">228</span>, <span class="comment">// '\x84'
<a href=#135 id=135 data-nosnippet>135</a> </span><span class="number">197</span>, <span class="comment">// '\x85'
<a href=#136 id=136 data-nosnippet>136</a> </span><span class="number">169</span>, <span class="comment">// '\x86'
<a href=#137 id=137 data-nosnippet>137</a> </span><span class="number">159</span>, <span class="comment">// '\x87'
<a href=#138 id=138 data-nosnippet>138</a> </span><span class="number">131</span>, <span class="comment">// '\x88'
<a href=#139 id=139 data-nosnippet>139</a> </span><span class="number">172</span>, <span class="comment">// '\x89'
<a href=#140 id=140 data-nosnippet>140</a> </span><span class="number">105</span>, <span class="comment">// '\x8a'
<a href=#141 id=141 data-nosnippet>141</a> </span><span class="number">80</span>, <span class="comment">// '\x8b'
<a href=#142 id=142 data-nosnippet>142</a> </span><span class="number">98</span>, <span class="comment">// '\x8c'
<a href=#143 id=143 data-nosnippet>143</a> </span><span class="number">96</span>, <span class="comment">// '\x8d'
<a href=#144 id=144 data-nosnippet>144</a> </span><span class="number">97</span>, <span class="comment">// '\x8e'
<a href=#145 id=145 data-nosnippet>145</a> </span><span class="number">81</span>, <span class="comment">// '\x8f'
<a href=#146 id=146 data-nosnippet>146</a> </span><span class="number">207</span>, <span class="comment">// '\x90'
<a href=#147 id=147 data-nosnippet>147</a> </span><span class="number">145</span>, <span class="comment">// '\x91'
<a href=#148 id=148 data-nosnippet>148</a> </span><span class="number">116</span>, <span class="comment">// '\x92'
<a href=#149 id=149 data-nosnippet>149</a> </span><span class="number">115</span>, <span class="comment">// '\x93'
<a href=#150 id=150 data-nosnippet>150</a> </span><span class="number">144</span>, <span class="comment">// '\x94'
<a href=#151 id=151 data-nosnippet>151</a> </span><span class="number">130</span>, <span class="comment">// '\x95'
<a href=#152 id=152 data-nosnippet>152</a> </span><span class="number">153</span>, <span class="comment">// '\x96'
<a href=#153 id=153 data-nosnippet>153</a> </span><span class="number">121</span>, <span class="comment">// '\x97'
<a href=#154 id=154 data-nosnippet>154</a> </span><span class="number">107</span>, <span class="comment">// '\x98'
<a href=#155 id=155 data-nosnippet>155</a> </span><span class="number">132</span>, <span class="comment">// '\x99'
<a href=#156 id=156 data-nosnippet>156</a> </span><span class="number">109</span>, <span class="comment">// '\x9a'
<a href=#157 id=157 data-nosnippet>157</a> </span><span class="number">110</span>, <span class="comment">// '\x9b'
<a href=#158 id=158 data-nosnippet>158</a> </span><span class="number">124</span>, <span class="comment">// '\x9c'
<a href=#159 id=159 data-nosnippet>159</a> </span><span class="number">111</span>, <span class="comment">// '\x9d'
<a href=#160 id=160 data-nosnippet>160</a> </span><span class="number">82</span>, <span class="comment">// '\x9e'
<a href=#161 id=161 data-nosnippet>161</a> </span><span class="number">108</span>, <span class="comment">// '\x9f'
<a href=#162 id=162 data-nosnippet>162</a> </span><span class="number">118</span>, <span class="comment">// '\xa0'
<a href=#163 id=163 data-nosnippet>163</a> </span><span class="number">141</span>, <span class="comment">// '¡'
<a href=#164 id=164 data-nosnippet>164</a> </span><span class="number">113</span>, <span class="comment">// '¢'
<a href=#165 id=165 data-nosnippet>165</a> </span><span class="number">129</span>, <span class="comment">// '£'
<a href=#166 id=166 data-nosnippet>166</a> </span><span class="number">119</span>, <span class="comment">// '¤'
<a href=#167 id=167 data-nosnippet>167</a> </span><span class="number">125</span>, <span class="comment">// '¥'
<a href=#168 id=168 data-nosnippet>168</a> </span><span class="number">165</span>, <span class="comment">// '¦'
<a href=#169 id=169 data-nosnippet>169</a> </span><span class="number">117</span>, <span class="comment">// '§'
<a href=#170 id=170 data-nosnippet>170</a> </span><span class="number">92</span>, <span class="comment">// '¨'
<a href=#171 id=171 data-nosnippet>171</a> </span><span class="number">106</span>, <span class="comment">// '©'
<a href=#172 id=172 data-nosnippet>172</a> </span><span class="number">83</span>, <span class="comment">// 'ª'
<a href=#173 id=173 data-nosnippet>173</a> </span><span class="number">72</span>, <span class="comment">// '«'
<a href=#174 id=174 data-nosnippet>174</a> </span><span class="number">99</span>, <span class="comment">// '¬'
<a href=#175 id=175 data-nosnippet>175</a> </span><span class="number">93</span>, <span class="comment">// '\xad'
<a href=#176 id=176 data-nosnippet>176</a> </span><span class="number">65</span>, <span class="comment">// '®'
<a href=#177 id=177 data-nosnippet>177</a> </span><span class="number">79</span>, <span class="comment">// '¯'
<a href=#178 id=178 data-nosnippet>178</a> </span><span class="number">166</span>, <span class="comment">// '°'
<a href=#179 id=179 data-nosnippet>179</a> </span><span class="number">237</span>, <span class="comment">// '±'
<a href=#180 id=180 data-nosnippet>180</a> </span><span class="number">163</span>, <span class="comment">// '²'
<a href=#181 id=181 data-nosnippet>181</a> </span><span class="number">199</span>, <span class="comment">// '³'
<a href=#182 id=182 data-nosnippet>182</a> </span><span class="number">190</span>, <span class="comment">// '´'
<a href=#183 id=183 data-nosnippet>183</a> </span><span class="number">225</span>, <span class="comment">// 'µ'
<a href=#184 id=184 data-nosnippet>184</a> </span><span class="number">209</span>, <span class="comment">// '¶'
<a href=#185 id=185 data-nosnippet>185</a> </span><span class="number">203</span>, <span class="comment">// '·'
<a href=#186 id=186 data-nosnippet>186</a> </span><span class="number">198</span>, <span class="comment">// '¸'
<a href=#187 id=187 data-nosnippet>187</a> </span><span class="number">217</span>, <span class="comment">// '¹'
<a href=#188 id=188 data-nosnippet>188</a> </span><span class="number">219</span>, <span class="comment">// 'º'
<a href=#189 id=189 data-nosnippet>189</a> </span><span class="number">206</span>, <span class="comment">// '»'
<a href=#190 id=190 data-nosnippet>190</a> </span><span class="number">234</span>, <span class="comment">// '¼'
<a href=#191 id=191 data-nosnippet>191</a> </span><span class="number">248</span>, <span class="comment">// '½'
<a href=#192 id=192 data-nosnippet>192</a> </span><span class="number">158</span>, <span class="comment">// '¾'
<a href=#193 id=193 data-nosnippet>193</a> </span><span class="number">239</span>, <span class="comment">// '¿'
<a href=#194 id=194 data-nosnippet>194</a> </span><span class="number">255</span>, <span class="comment">// 'À'
<a href=#195 id=195 data-nosnippet>195</a> </span><span class="number">255</span>, <span class="comment">// 'Á'
<a href=#196 id=196 data-nosnippet>196</a> </span><span class="number">255</span>, <span class="comment">// 'Â'
<a href=#197 id=197 data-nosnippet>197</a> </span><span class="number">255</span>, <span class="comment">// 'Ã'
<a href=#198 id=198 data-nosnippet>198</a> </span><span class="number">255</span>, <span class="comment">// 'Ä'
<a href=#199 id=199 data-nosnippet>199</a> </span><span class="number">255</span>, <span class="comment">// 'Å'
<a href=#200 id=200 data-nosnippet>200</a> </span><span class="number">255</span>, <span class="comment">// 'Æ'
<a href=#201 id=201 data-nosnippet>201</a> </span><span class="number">255</span>, <span class="comment">// 'Ç'
<a href=#202 id=202 data-nosnippet>202</a> </span><span class="number">255</span>, <span class="comment">// 'È'
<a href=#203 id=203 data-nosnippet>203</a> </span><span class="number">255</span>, <span class="comment">// 'É'
<a href=#204 id=204 data-nosnippet>204</a> </span><span class="number">255</span>, <span class="comment">// 'Ê'
<a href=#205 id=205 data-nosnippet>205</a> </span><span class="number">255</span>, <span class="comment">// 'Ë'
<a href=#206 id=206 data-nosnippet>206</a> </span><span class="number">255</span>, <span class="comment">// 'Ì'
<a href=#207 id=207 data-nosnippet>207</a> </span><span class="number">255</span>, <span class="comment">// 'Í'
<a href=#208 id=208 data-nosnippet>208</a> </span><span class="number">255</span>, <span class="comment">// 'Î'
<a href=#209 id=209 data-nosnippet>209</a> </span><span class="number">255</span>, <span class="comment">// 'Ï'
<a href=#210 id=210 data-nosnippet>210</a> </span><span class="number">255</span>, <span class="comment">// 'Ð'
<a href=#211 id=211 data-nosnippet>211</a> </span><span class="number">255</span>, <span class="comment">// 'Ñ'
<a href=#212 id=212 data-nosnippet>212</a> </span><span class="number">255</span>, <span class="comment">// 'Ò'
<a href=#213 id=213 data-nosnippet>213</a> </span><span class="number">255</span>, <span class="comment">// 'Ó'
<a href=#214 id=214 data-nosnippet>214</a> </span><span class="number">255</span>, <span class="comment">// 'Ô'
<a href=#215 id=215 data-nosnippet>215</a> </span><span class="number">255</span>, <span class="comment">// 'Õ'
<a href=#216 id=216 data-nosnippet>216</a> </span><span class="number">255</span>, <span class="comment">// 'Ö'
<a href=#217 id=217 data-nosnippet>217</a> </span><span class="number">255</span>, <span class="comment">// '×'
<a href=#218 id=218 data-nosnippet>218</a> </span><span class="number">255</span>, <span class="comment">// 'Ø'
<a href=#219 id=219 data-nosnippet>219</a> </span><span class="number">255</span>, <span class="comment">// 'Ù'
<a href=#220 id=220 data-nosnippet>220</a> </span><span class="number">255</span>, <span class="comment">// 'Ú'
<a href=#221 id=221 data-nosnippet>221</a> </span><span class="number">255</span>, <span class="comment">// 'Û'
<a href=#222 id=222 data-nosnippet>222</a> </span><span class="number">255</span>, <span class="comment">// 'Ü'
<a href=#223 id=223 data-nosnippet>223</a> </span><span class="number">255</span>, <span class="comment">// 'Ý'
<a href=#224 id=224 data-nosnippet>224</a> </span><span class="number">255</span>, <span class="comment">// 'Þ'
<a href=#225 id=225 data-nosnippet>225</a> </span><span class="number">255</span>, <span class="comment">// 'ß'
<a href=#226 id=226 data-nosnippet>226</a> </span><span class="number">255</span>, <span class="comment">// 'à'
<a href=#227 id=227 data-nosnippet>227</a> </span><span class="number">255</span>, <span class="comment">// 'á'
<a href=#228 id=228 data-nosnippet>228</a> </span><span class="number">255</span>, <span class="comment">// 'â'
<a href=#229 id=229 data-nosnippet>229</a> </span><span class="number">255</span>, <span class="comment">// 'ã'
<a href=#230 id=230 data-nosnippet>230</a> </span><span class="number">255</span>, <span class="comment">// 'ä'
<a href=#231 id=231 data-nosnippet>231</a> </span><span class="number">255</span>, <span class="comment">// 'å'
<a href=#232 id=232 data-nosnippet>232</a> </span><span class="number">255</span>, <span class="comment">// 'æ'
<a href=#233 id=233 data-nosnippet>233</a> </span><span class="number">255</span>, <span class="comment">// 'ç'
<a href=#234 id=234 data-nosnippet>234</a> </span><span class="number">255</span>, <span class="comment">// 'è'
<a href=#235 id=235 data-nosnippet>235</a> </span><span class="number">255</span>, <span class="comment">// 'é'
<a href=#236 id=236 data-nosnippet>236</a> </span><span class="number">255</span>, <span class="comment">// 'ê'
<a href=#237 id=237 data-nosnippet>237</a> </span><span class="number">255</span>, <span class="comment">// 'ë'
<a href=#238 id=238 data-nosnippet>238</a> </span><span class="number">255</span>, <span class="comment">// 'ì'
<a href=#239 id=239 data-nosnippet>239</a> </span><span class="number">255</span>, <span class="comment">// 'í'
<a href=#240 id=240 data-nosnippet>240</a> </span><span class="number">255</span>, <span class="comment">// 'î'
<a href=#241 id=241 data-nosnippet>241</a> </span><span class="number">255</span>, <span class="comment">// 'ï'
<a href=#242 id=242 data-nosnippet>242</a> </span><span class="number">255</span>, <span class="comment">// 'ð'
<a href=#243 id=243 data-nosnippet>243</a> </span><span class="number">255</span>, <span class="comment">// 'ñ'
<a href=#244 id=244 data-nosnippet>244</a> </span><span class="number">255</span>, <span class="comment">// 'ò'
<a href=#245 id=245 data-nosnippet>245</a> </span><span class="number">255</span>, <span class="comment">// 'ó'
<a href=#246 id=246 data-nosnippet>246</a> </span><span class="number">255</span>, <span class="comment">// 'ô'
<a href=#247 id=247 data-nosnippet>247</a> </span><span class="number">255</span>, <span class="comment">// 'õ'
<a href=#248 id=248 data-nosnippet>248</a> </span><span class="number">255</span>, <span class="comment">// 'ö'
<a href=#249 id=249 data-nosnippet>249</a> </span><span class="number">255</span>, <span class="comment">// '÷'
<a href=#250 id=250 data-nosnippet>250</a> </span><span class="number">255</span>, <span class="comment">// 'ø'
<a href=#251 id=251 data-nosnippet>251</a> </span><span class="number">255</span>, <span class="comment">// 'ù'
<a href=#252 id=252 data-nosnippet>252</a> </span><span class="number">255</span>, <span class="comment">// 'ú'
<a href=#253 id=253 data-nosnippet>253</a> </span><span class="number">255</span>, <span class="comment">// 'û'
<a href=#254 id=254 data-nosnippet>254</a> </span><span class="number">255</span>, <span class="comment">// 'ü'
<a href=#255 id=255 data-nosnippet>255</a> </span><span class="number">255</span>, <span class="comment">// 'ý'
<a href=#256 id=256 data-nosnippet>256</a> </span><span class="number">255</span>, <span class="comment">// 'þ'
<a href=#257 id=257 data-nosnippet>257</a> </span><span class="number">255</span>, <span class="comment">// 'ÿ'
<a href=#258 id=258 data-nosnippet>258</a></span>];
</code></pre></div></section></main></body></html>

View File

@@ -0,0 +1,27 @@
<!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 `/home/newkirk/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/aho-corasick-1.1.4/src/util/debug.rs`."><title>debug.rs - source</title><script>if(window.location.protocol!=="file:")document.head.insertAdjacentHTML("beforeend","SourceSerif4-Regular-6b053e98.ttf.woff2,FiraSans-Italic-81dc35de.woff2,FiraSans-Regular-0fe48ade.woff2,FiraSans-MediumItalic-ccf7e434.woff2,FiraSans-Medium-e1aa3f0a.woff2,SourceCodePro-Regular-8badfe75.ttf.woff2,SourceCodePro-Semibold-aa29a496.ttf.woff2".split(",").map(f=>`<link rel="preload" as="font" type="font/woff2"href="../../../static.files/${f}">`).join(""))</script><link rel="stylesheet" href="../../../static.files/normalize-9960930a.css"><link rel="stylesheet" href="../../../static.files/rustdoc-ca0dd0c4.css"><meta name="rustdoc-vars" data-root-path="../../../" data-static-root-path="../../../static.files/" data-current-crate="aho_corasick" data-themes="" data-resource-suffix="" data-rustdoc-version="1.93.1 (01f6ddf75 2026-02-11) (Arch Linux rust 1:1.93.1-1)" data-channel="1.93.1" data-search-js="search-9e2438ea.js" data-stringdex-js="stringdex-a3946164.js" data-settings-js="settings-c38705f0.js" ><script src="../../../static.files/storage-e2aeef58.js"></script><script defer src="../../../static.files/src-script-813739b1.js"></script><script defer src="../../../src-files.js"></script><script defer src="../../../static.files/main-a410ff4d.js"></script><noscript><link rel="stylesheet" href="../../../static.files/noscript-263c88ec.css"></noscript><link rel="alternate icon" type="image/png" href="../../../static.files/favicon-32x32-eab170b8.png"><link rel="icon" type="image/svg+xml" href="../../../static.files/favicon-044be391.svg"></head><body class="rustdoc src"><!--[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="src-sidebar-title"><h2>Files</h2></div></nav><div class="sidebar-resizer" title="Drag to resize sidebar"></div><main><section id="main-content" class="content"><div class="main-heading"><h1><div class="sub-heading">aho_corasick/util/</div>debug.rs</h1><rustdoc-toolbar></rustdoc-toolbar></div><div class="example-wrap digits-2"><pre class="rust"><code><a href=#1 id=1 data-nosnippet>1</a><span class="doccomment">/// A type that wraps a single byte with a convenient fmt::Debug impl that
<a href=#2 id=2 data-nosnippet>2</a>/// escapes the byte.
<a href=#3 id=3 data-nosnippet>3</a></span><span class="kw">pub</span>(<span class="kw">crate</span>) <span class="kw">struct </span>DebugByte(<span class="kw">pub</span>(<span class="kw">crate</span>) u8);
<a href=#4 id=4 data-nosnippet>4</a>
<a href=#5 id=5 data-nosnippet>5</a><span class="kw">impl </span>core::fmt::Debug <span class="kw">for </span>DebugByte {
<a href=#6 id=6 data-nosnippet>6</a> <span class="kw">fn </span>fmt(<span class="kw-2">&amp;</span><span class="self">self</span>, f: <span class="kw-2">&amp;mut </span>core::fmt::Formatter) -&gt; core::fmt::Result {
<a href=#7 id=7 data-nosnippet>7</a> <span class="comment">// Special case ASCII space. It's too hard to read otherwise, so
<a href=#8 id=8 data-nosnippet>8</a> // put quotes around it. I sometimes wonder whether just '\x20' would
<a href=#9 id=9 data-nosnippet>9</a> // be better...
<a href=#10 id=10 data-nosnippet>10</a> </span><span class="kw">if </span><span class="self">self</span>.<span class="number">0 </span>== <span class="string">b' ' </span>{
<a href=#11 id=11 data-nosnippet>11</a> <span class="kw">return </span><span class="macro">write!</span>(f, <span class="string">"' '"</span>);
<a href=#12 id=12 data-nosnippet>12</a> }
<a href=#13 id=13 data-nosnippet>13</a> <span class="comment">// 10 bytes is enough to cover any output from ascii::escape_default.
<a href=#14 id=14 data-nosnippet>14</a> </span><span class="kw">let </span><span class="kw-2">mut </span>bytes = [<span class="number">0u8</span>; <span class="number">10</span>];
<a href=#15 id=15 data-nosnippet>15</a> <span class="kw">let </span><span class="kw-2">mut </span>len = <span class="number">0</span>;
<a href=#16 id=16 data-nosnippet>16</a> <span class="kw">for </span>(i, <span class="kw-2">mut </span>b) <span class="kw">in </span>core::ascii::escape_default(<span class="self">self</span>.<span class="number">0</span>).enumerate() {
<a href=#17 id=17 data-nosnippet>17</a> <span class="comment">// capitalize \xab to \xAB
<a href=#18 id=18 data-nosnippet>18</a> </span><span class="kw">if </span>i &gt;= <span class="number">2 </span>&amp;&amp; <span class="string">b'a' </span>&lt;= b &amp;&amp; b &lt;= <span class="string">b'f' </span>{
<a href=#19 id=19 data-nosnippet>19</a> b -= <span class="number">32</span>;
<a href=#20 id=20 data-nosnippet>20</a> }
<a href=#21 id=21 data-nosnippet>21</a> bytes[len] = b;
<a href=#22 id=22 data-nosnippet>22</a> len += <span class="number">1</span>;
<a href=#23 id=23 data-nosnippet>23</a> }
<a href=#24 id=24 data-nosnippet>24</a> <span class="macro">write!</span>(f, <span class="string">"{}"</span>, core::str::from_utf8(<span class="kw-2">&amp;</span>bytes[..len]).unwrap())
<a href=#25 id=25 data-nosnippet>25</a> }
<a href=#26 id=26 data-nosnippet>26</a>}
</code></pre></div></section></main></body></html>

View File

@@ -0,0 +1,260 @@
<!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 `/home/newkirk/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/aho-corasick-1.1.4/src/util/error.rs`."><title>error.rs - source</title><script>if(window.location.protocol!=="file:")document.head.insertAdjacentHTML("beforeend","SourceSerif4-Regular-6b053e98.ttf.woff2,FiraSans-Italic-81dc35de.woff2,FiraSans-Regular-0fe48ade.woff2,FiraSans-MediumItalic-ccf7e434.woff2,FiraSans-Medium-e1aa3f0a.woff2,SourceCodePro-Regular-8badfe75.ttf.woff2,SourceCodePro-Semibold-aa29a496.ttf.woff2".split(",").map(f=>`<link rel="preload" as="font" type="font/woff2"href="../../../static.files/${f}">`).join(""))</script><link rel="stylesheet" href="../../../static.files/normalize-9960930a.css"><link rel="stylesheet" href="../../../static.files/rustdoc-ca0dd0c4.css"><meta name="rustdoc-vars" data-root-path="../../../" data-static-root-path="../../../static.files/" data-current-crate="aho_corasick" data-themes="" data-resource-suffix="" data-rustdoc-version="1.93.1 (01f6ddf75 2026-02-11) (Arch Linux rust 1:1.93.1-1)" data-channel="1.93.1" data-search-js="search-9e2438ea.js" data-stringdex-js="stringdex-a3946164.js" data-settings-js="settings-c38705f0.js" ><script src="../../../static.files/storage-e2aeef58.js"></script><script defer src="../../../static.files/src-script-813739b1.js"></script><script defer src="../../../src-files.js"></script><script defer src="../../../static.files/main-a410ff4d.js"></script><noscript><link rel="stylesheet" href="../../../static.files/noscript-263c88ec.css"></noscript><link rel="alternate icon" type="image/png" href="../../../static.files/favicon-32x32-eab170b8.png"><link rel="icon" type="image/svg+xml" href="../../../static.files/favicon-044be391.svg"></head><body class="rustdoc src"><!--[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="src-sidebar-title"><h2>Files</h2></div></nav><div class="sidebar-resizer" title="Drag to resize sidebar"></div><main><section id="main-content" class="content"><div class="main-heading"><h1><div class="sub-heading">aho_corasick/util/</div>error.rs</h1><rustdoc-toolbar></rustdoc-toolbar></div><div class="example-wrap digits-3"><pre class="rust"><code><a href=#1 id=1 data-nosnippet>1</a><span class="kw">use </span><span class="kw">crate</span>::util::{
<a href=#2 id=2 data-nosnippet>2</a> primitives::{PatternID, SmallIndex},
<a href=#3 id=3 data-nosnippet>3</a> search::MatchKind,
<a href=#4 id=4 data-nosnippet>4</a>};
<a href=#5 id=5 data-nosnippet>5</a>
<a href=#6 id=6 data-nosnippet>6</a><span class="doccomment">/// An error that occurred during the construction of an Aho-Corasick
<a href=#7 id=7 data-nosnippet>7</a>/// automaton.
<a href=#8 id=8 data-nosnippet>8</a>///
<a href=#9 id=9 data-nosnippet>9</a>/// Build errors occur when some kind of limit has been exceeded, either in the
<a href=#10 id=10 data-nosnippet>10</a>/// number of states, the number of patterns of the length of a pattern. These
<a href=#11 id=11 data-nosnippet>11</a>/// limits aren't part of the public API, but they should generally be large
<a href=#12 id=12 data-nosnippet>12</a>/// enough to handle most use cases.
<a href=#13 id=13 data-nosnippet>13</a>///
<a href=#14 id=14 data-nosnippet>14</a>/// When the `std` feature is enabled, this implements the `std::error::Error`
<a href=#15 id=15 data-nosnippet>15</a>/// trait.
<a href=#16 id=16 data-nosnippet>16</a></span><span class="attr">#[derive(Clone, Debug)]
<a href=#17 id=17 data-nosnippet>17</a></span><span class="kw">pub struct </span>BuildError {
<a href=#18 id=18 data-nosnippet>18</a> kind: ErrorKind,
<a href=#19 id=19 data-nosnippet>19</a>}
<a href=#20 id=20 data-nosnippet>20</a>
<a href=#21 id=21 data-nosnippet>21</a><span class="doccomment">/// The kind of error that occurred.
<a href=#22 id=22 data-nosnippet>22</a></span><span class="attr">#[derive(Clone, Debug)]
<a href=#23 id=23 data-nosnippet>23</a></span><span class="kw">enum </span>ErrorKind {
<a href=#24 id=24 data-nosnippet>24</a> <span class="doccomment">/// An error that occurs when allocating a new state would result in an
<a href=#25 id=25 data-nosnippet>25</a> /// identifier that exceeds the capacity of a `StateID`.
<a href=#26 id=26 data-nosnippet>26</a> </span>StateIDOverflow {
<a href=#27 id=27 data-nosnippet>27</a> <span class="doccomment">/// The maximum possible id.
<a href=#28 id=28 data-nosnippet>28</a> </span>max: u64,
<a href=#29 id=29 data-nosnippet>29</a> <span class="doccomment">/// The maximum ID requested.
<a href=#30 id=30 data-nosnippet>30</a> </span>requested_max: u64,
<a href=#31 id=31 data-nosnippet>31</a> },
<a href=#32 id=32 data-nosnippet>32</a> <span class="doccomment">/// An error that occurs when adding a pattern to an Aho-Corasick
<a href=#33 id=33 data-nosnippet>33</a> /// automaton would result in an identifier that exceeds the capacity of a
<a href=#34 id=34 data-nosnippet>34</a> /// `PatternID`.
<a href=#35 id=35 data-nosnippet>35</a> </span>PatternIDOverflow {
<a href=#36 id=36 data-nosnippet>36</a> <span class="doccomment">/// The maximum possible id.
<a href=#37 id=37 data-nosnippet>37</a> </span>max: u64,
<a href=#38 id=38 data-nosnippet>38</a> <span class="doccomment">/// The maximum ID requested.
<a href=#39 id=39 data-nosnippet>39</a> </span>requested_max: u64,
<a href=#40 id=40 data-nosnippet>40</a> },
<a href=#41 id=41 data-nosnippet>41</a> <span class="doccomment">/// Occurs when a pattern string is given to the Aho-Corasick constructor
<a href=#42 id=42 data-nosnippet>42</a> /// that is too long.
<a href=#43 id=43 data-nosnippet>43</a> </span>PatternTooLong {
<a href=#44 id=44 data-nosnippet>44</a> <span class="doccomment">/// The ID of the pattern that was too long.
<a href=#45 id=45 data-nosnippet>45</a> </span>pattern: PatternID,
<a href=#46 id=46 data-nosnippet>46</a> <span class="doccomment">/// The length that was too long.
<a href=#47 id=47 data-nosnippet>47</a> </span>len: usize,
<a href=#48 id=48 data-nosnippet>48</a> },
<a href=#49 id=49 data-nosnippet>49</a>}
<a href=#50 id=50 data-nosnippet>50</a>
<a href=#51 id=51 data-nosnippet>51</a><span class="kw">impl </span>BuildError {
<a href=#52 id=52 data-nosnippet>52</a> <span class="kw">pub</span>(<span class="kw">crate</span>) <span class="kw">fn </span>state_id_overflow(
<a href=#53 id=53 data-nosnippet>53</a> max: u64,
<a href=#54 id=54 data-nosnippet>54</a> requested_max: u64,
<a href=#55 id=55 data-nosnippet>55</a> ) -&gt; BuildError {
<a href=#56 id=56 data-nosnippet>56</a> BuildError { kind: ErrorKind::StateIDOverflow { max, requested_max } }
<a href=#57 id=57 data-nosnippet>57</a> }
<a href=#58 id=58 data-nosnippet>58</a>
<a href=#59 id=59 data-nosnippet>59</a> <span class="kw">pub</span>(<span class="kw">crate</span>) <span class="kw">fn </span>pattern_id_overflow(
<a href=#60 id=60 data-nosnippet>60</a> max: u64,
<a href=#61 id=61 data-nosnippet>61</a> requested_max: u64,
<a href=#62 id=62 data-nosnippet>62</a> ) -&gt; BuildError {
<a href=#63 id=63 data-nosnippet>63</a> BuildError {
<a href=#64 id=64 data-nosnippet>64</a> kind: ErrorKind::PatternIDOverflow { max, requested_max },
<a href=#65 id=65 data-nosnippet>65</a> }
<a href=#66 id=66 data-nosnippet>66</a> }
<a href=#67 id=67 data-nosnippet>67</a>
<a href=#68 id=68 data-nosnippet>68</a> <span class="kw">pub</span>(<span class="kw">crate</span>) <span class="kw">fn </span>pattern_too_long(
<a href=#69 id=69 data-nosnippet>69</a> pattern: PatternID,
<a href=#70 id=70 data-nosnippet>70</a> len: usize,
<a href=#71 id=71 data-nosnippet>71</a> ) -&gt; BuildError {
<a href=#72 id=72 data-nosnippet>72</a> BuildError { kind: ErrorKind::PatternTooLong { pattern, len } }
<a href=#73 id=73 data-nosnippet>73</a> }
<a href=#74 id=74 data-nosnippet>74</a>}
<a href=#75 id=75 data-nosnippet>75</a>
<a href=#76 id=76 data-nosnippet>76</a><span class="attr">#[cfg(feature = <span class="string">"std"</span>)]
<a href=#77 id=77 data-nosnippet>77</a></span><span class="kw">impl </span>std::error::Error <span class="kw">for </span>BuildError {}
<a href=#78 id=78 data-nosnippet>78</a>
<a href=#79 id=79 data-nosnippet>79</a><span class="kw">impl </span>core::fmt::Display <span class="kw">for </span>BuildError {
<a href=#80 id=80 data-nosnippet>80</a> <span class="kw">fn </span>fmt(<span class="kw-2">&amp;</span><span class="self">self</span>, f: <span class="kw-2">&amp;mut </span>core::fmt::Formatter&lt;<span class="lifetime">'_</span>&gt;) -&gt; core::fmt::Result {
<a href=#81 id=81 data-nosnippet>81</a> <span class="kw">match </span><span class="self">self</span>.kind {
<a href=#82 id=82 data-nosnippet>82</a> ErrorKind::StateIDOverflow { max, requested_max } =&gt; {
<a href=#83 id=83 data-nosnippet>83</a> <span class="macro">write!</span>(
<a href=#84 id=84 data-nosnippet>84</a> f,
<a href=#85 id=85 data-nosnippet>85</a> <span class="string">"state identifier overflow: failed to create state ID \
<a href=#86 id=86 data-nosnippet>86</a> from {}, which exceeds the max of {}"</span>,
<a href=#87 id=87 data-nosnippet>87</a> requested_max, max,
<a href=#88 id=88 data-nosnippet>88</a> )
<a href=#89 id=89 data-nosnippet>89</a> }
<a href=#90 id=90 data-nosnippet>90</a> ErrorKind::PatternIDOverflow { max, requested_max } =&gt; {
<a href=#91 id=91 data-nosnippet>91</a> <span class="macro">write!</span>(
<a href=#92 id=92 data-nosnippet>92</a> f,
<a href=#93 id=93 data-nosnippet>93</a> <span class="string">"pattern identifier overflow: failed to create pattern ID \
<a href=#94 id=94 data-nosnippet>94</a> from {}, which exceeds the max of {}"</span>,
<a href=#95 id=95 data-nosnippet>95</a> requested_max, max,
<a href=#96 id=96 data-nosnippet>96</a> )
<a href=#97 id=97 data-nosnippet>97</a> }
<a href=#98 id=98 data-nosnippet>98</a> ErrorKind::PatternTooLong { pattern, len } =&gt; {
<a href=#99 id=99 data-nosnippet>99</a> <span class="macro">write!</span>(
<a href=#100 id=100 data-nosnippet>100</a> f,
<a href=#101 id=101 data-nosnippet>101</a> <span class="string">"pattern {} with length {} exceeds \
<a href=#102 id=102 data-nosnippet>102</a> the maximum pattern length of {}"</span>,
<a href=#103 id=103 data-nosnippet>103</a> pattern.as_usize(),
<a href=#104 id=104 data-nosnippet>104</a> len,
<a href=#105 id=105 data-nosnippet>105</a> SmallIndex::MAX.as_usize(),
<a href=#106 id=106 data-nosnippet>106</a> )
<a href=#107 id=107 data-nosnippet>107</a> }
<a href=#108 id=108 data-nosnippet>108</a> }
<a href=#109 id=109 data-nosnippet>109</a> }
<a href=#110 id=110 data-nosnippet>110</a>}
<a href=#111 id=111 data-nosnippet>111</a>
<a href=#112 id=112 data-nosnippet>112</a><span class="doccomment">/// An error that occurred during an Aho-Corasick search.
<a href=#113 id=113 data-nosnippet>113</a>///
<a href=#114 id=114 data-nosnippet>114</a>/// An error that occurs during a search is limited to some kind of
<a href=#115 id=115 data-nosnippet>115</a>/// misconfiguration that resulted in an illegal call. Stated differently,
<a href=#116 id=116 data-nosnippet>116</a>/// whether an error occurs is not dependent on the specific bytes in the
<a href=#117 id=117 data-nosnippet>117</a>/// haystack.
<a href=#118 id=118 data-nosnippet>118</a>///
<a href=#119 id=119 data-nosnippet>119</a>/// Examples of misconfiguration:
<a href=#120 id=120 data-nosnippet>120</a>///
<a href=#121 id=121 data-nosnippet>121</a>/// * Executing a stream or overlapping search on a searcher that was built was
<a href=#122 id=122 data-nosnippet>122</a>/// something other than [`MatchKind::Standard`](crate::MatchKind::Standard)
<a href=#123 id=123 data-nosnippet>123</a>/// semantics.
<a href=#124 id=124 data-nosnippet>124</a>/// * Requested an anchored or an unanchored search on a searcher that doesn't
<a href=#125 id=125 data-nosnippet>125</a>/// support unanchored or anchored searches, respectively.
<a href=#126 id=126 data-nosnippet>126</a>///
<a href=#127 id=127 data-nosnippet>127</a>/// When the `std` feature is enabled, this implements the `std::error::Error`
<a href=#128 id=128 data-nosnippet>128</a>/// trait.
<a href=#129 id=129 data-nosnippet>129</a></span><span class="attr">#[derive(Clone, Debug, Eq, PartialEq)]
<a href=#130 id=130 data-nosnippet>130</a></span><span class="kw">pub struct </span>MatchError(alloc::boxed::Box&lt;MatchErrorKind&gt;);
<a href=#131 id=131 data-nosnippet>131</a>
<a href=#132 id=132 data-nosnippet>132</a><span class="kw">impl </span>MatchError {
<a href=#133 id=133 data-nosnippet>133</a> <span class="doccomment">/// Create a new error value with the given kind.
<a href=#134 id=134 data-nosnippet>134</a> ///
<a href=#135 id=135 data-nosnippet>135</a> /// This is a more verbose version of the kind-specific constructors, e.g.,
<a href=#136 id=136 data-nosnippet>136</a> /// `MatchError::unsupported_stream`.
<a href=#137 id=137 data-nosnippet>137</a> </span><span class="kw">pub fn </span>new(kind: MatchErrorKind) -&gt; MatchError {
<a href=#138 id=138 data-nosnippet>138</a> MatchError(alloc::boxed::Box::new(kind))
<a href=#139 id=139 data-nosnippet>139</a> }
<a href=#140 id=140 data-nosnippet>140</a>
<a href=#141 id=141 data-nosnippet>141</a> <span class="doccomment">/// Returns a reference to the underlying error kind.
<a href=#142 id=142 data-nosnippet>142</a> </span><span class="kw">pub fn </span>kind(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; <span class="kw-2">&amp;</span>MatchErrorKind {
<a href=#143 id=143 data-nosnippet>143</a> <span class="kw-2">&amp;</span><span class="self">self</span>.<span class="number">0
<a href=#144 id=144 data-nosnippet>144</a> </span>}
<a href=#145 id=145 data-nosnippet>145</a>
<a href=#146 id=146 data-nosnippet>146</a> <span class="doccomment">/// Create a new "invalid anchored search" error. This occurs when the
<a href=#147 id=147 data-nosnippet>147</a> /// caller requests an anchored search but where anchored searches aren't
<a href=#148 id=148 data-nosnippet>148</a> /// supported.
<a href=#149 id=149 data-nosnippet>149</a> ///
<a href=#150 id=150 data-nosnippet>150</a> /// This is the same as calling `MatchError::new` with a
<a href=#151 id=151 data-nosnippet>151</a> /// [`MatchErrorKind::InvalidInputAnchored`] kind.
<a href=#152 id=152 data-nosnippet>152</a> </span><span class="kw">pub fn </span>invalid_input_anchored() -&gt; MatchError {
<a href=#153 id=153 data-nosnippet>153</a> MatchError::new(MatchErrorKind::InvalidInputAnchored)
<a href=#154 id=154 data-nosnippet>154</a> }
<a href=#155 id=155 data-nosnippet>155</a>
<a href=#156 id=156 data-nosnippet>156</a> <span class="doccomment">/// Create a new "invalid unanchored search" error. This occurs when the
<a href=#157 id=157 data-nosnippet>157</a> /// caller requests an unanchored search but where unanchored searches
<a href=#158 id=158 data-nosnippet>158</a> /// aren't supported.
<a href=#159 id=159 data-nosnippet>159</a> ///
<a href=#160 id=160 data-nosnippet>160</a> /// This is the same as calling `MatchError::new` with a
<a href=#161 id=161 data-nosnippet>161</a> /// [`MatchErrorKind::InvalidInputUnanchored`] kind.
<a href=#162 id=162 data-nosnippet>162</a> </span><span class="kw">pub fn </span>invalid_input_unanchored() -&gt; MatchError {
<a href=#163 id=163 data-nosnippet>163</a> MatchError::new(MatchErrorKind::InvalidInputUnanchored)
<a href=#164 id=164 data-nosnippet>164</a> }
<a href=#165 id=165 data-nosnippet>165</a>
<a href=#166 id=166 data-nosnippet>166</a> <span class="doccomment">/// Create a new "unsupported stream search" error. This occurs when the
<a href=#167 id=167 data-nosnippet>167</a> /// caller requests a stream search while using an Aho-Corasick automaton
<a href=#168 id=168 data-nosnippet>168</a> /// with a match kind other than [`MatchKind::Standard`].
<a href=#169 id=169 data-nosnippet>169</a> ///
<a href=#170 id=170 data-nosnippet>170</a> /// The match kind given should be the match kind of the automaton. It
<a href=#171 id=171 data-nosnippet>171</a> /// should never be `MatchKind::Standard`.
<a href=#172 id=172 data-nosnippet>172</a> </span><span class="kw">pub fn </span>unsupported_stream(got: MatchKind) -&gt; MatchError {
<a href=#173 id=173 data-nosnippet>173</a> MatchError::new(MatchErrorKind::UnsupportedStream { got })
<a href=#174 id=174 data-nosnippet>174</a> }
<a href=#175 id=175 data-nosnippet>175</a>
<a href=#176 id=176 data-nosnippet>176</a> <span class="doccomment">/// Create a new "unsupported overlapping search" error. This occurs when
<a href=#177 id=177 data-nosnippet>177</a> /// the caller requests an overlapping search while using an Aho-Corasick
<a href=#178 id=178 data-nosnippet>178</a> /// automaton with a match kind other than [`MatchKind::Standard`].
<a href=#179 id=179 data-nosnippet>179</a> ///
<a href=#180 id=180 data-nosnippet>180</a> /// The match kind given should be the match kind of the automaton. It
<a href=#181 id=181 data-nosnippet>181</a> /// should never be `MatchKind::Standard`.
<a href=#182 id=182 data-nosnippet>182</a> </span><span class="kw">pub fn </span>unsupported_overlapping(got: MatchKind) -&gt; MatchError {
<a href=#183 id=183 data-nosnippet>183</a> MatchError::new(MatchErrorKind::UnsupportedOverlapping { got })
<a href=#184 id=184 data-nosnippet>184</a> }
<a href=#185 id=185 data-nosnippet>185</a>
<a href=#186 id=186 data-nosnippet>186</a> <span class="doccomment">/// Create a new "unsupported empty pattern" error. This occurs when the
<a href=#187 id=187 data-nosnippet>187</a> /// caller requests a search for which matching an automaton that contains
<a href=#188 id=188 data-nosnippet>188</a> /// an empty pattern string is not supported.
<a href=#189 id=189 data-nosnippet>189</a> </span><span class="kw">pub fn </span>unsupported_empty() -&gt; MatchError {
<a href=#190 id=190 data-nosnippet>190</a> MatchError::new(MatchErrorKind::UnsupportedEmpty)
<a href=#191 id=191 data-nosnippet>191</a> }
<a href=#192 id=192 data-nosnippet>192</a>}
<a href=#193 id=193 data-nosnippet>193</a>
<a href=#194 id=194 data-nosnippet>194</a><span class="doccomment">/// The underlying kind of a [`MatchError`].
<a href=#195 id=195 data-nosnippet>195</a>///
<a href=#196 id=196 data-nosnippet>196</a>/// This is a **non-exhaustive** enum. That means new variants may be added in
<a href=#197 id=197 data-nosnippet>197</a>/// a semver-compatible release.
<a href=#198 id=198 data-nosnippet>198</a></span><span class="attr">#[non_exhaustive]
<a href=#199 id=199 data-nosnippet>199</a>#[derive(Clone, Debug, Eq, PartialEq)]
<a href=#200 id=200 data-nosnippet>200</a></span><span class="kw">pub enum </span>MatchErrorKind {
<a href=#201 id=201 data-nosnippet>201</a> <span class="doccomment">/// An error indicating that an anchored search was requested, but from a
<a href=#202 id=202 data-nosnippet>202</a> /// searcher that was built without anchored support.
<a href=#203 id=203 data-nosnippet>203</a> </span>InvalidInputAnchored,
<a href=#204 id=204 data-nosnippet>204</a> <span class="doccomment">/// An error indicating that an unanchored search was requested, but from a
<a href=#205 id=205 data-nosnippet>205</a> /// searcher that was built without unanchored support.
<a href=#206 id=206 data-nosnippet>206</a> </span>InvalidInputUnanchored,
<a href=#207 id=207 data-nosnippet>207</a> <span class="doccomment">/// An error indicating that a stream search was attempted on an
<a href=#208 id=208 data-nosnippet>208</a> /// Aho-Corasick automaton with an unsupported `MatchKind`.
<a href=#209 id=209 data-nosnippet>209</a> </span>UnsupportedStream {
<a href=#210 id=210 data-nosnippet>210</a> <span class="doccomment">/// The match semantics for the automaton that was used.
<a href=#211 id=211 data-nosnippet>211</a> </span>got: MatchKind,
<a href=#212 id=212 data-nosnippet>212</a> },
<a href=#213 id=213 data-nosnippet>213</a> <span class="doccomment">/// An error indicating that an overlapping search was attempted on an
<a href=#214 id=214 data-nosnippet>214</a> /// Aho-Corasick automaton with an unsupported `MatchKind`.
<a href=#215 id=215 data-nosnippet>215</a> </span>UnsupportedOverlapping {
<a href=#216 id=216 data-nosnippet>216</a> <span class="doccomment">/// The match semantics for the automaton that was used.
<a href=#217 id=217 data-nosnippet>217</a> </span>got: MatchKind,
<a href=#218 id=218 data-nosnippet>218</a> },
<a href=#219 id=219 data-nosnippet>219</a> <span class="doccomment">/// An error indicating that the operation requested doesn't support
<a href=#220 id=220 data-nosnippet>220</a> /// automatons that contain an empty pattern string.
<a href=#221 id=221 data-nosnippet>221</a> </span>UnsupportedEmpty,
<a href=#222 id=222 data-nosnippet>222</a>}
<a href=#223 id=223 data-nosnippet>223</a>
<a href=#224 id=224 data-nosnippet>224</a><span class="attr">#[cfg(feature = <span class="string">"std"</span>)]
<a href=#225 id=225 data-nosnippet>225</a></span><span class="kw">impl </span>std::error::Error <span class="kw">for </span>MatchError {}
<a href=#226 id=226 data-nosnippet>226</a>
<a href=#227 id=227 data-nosnippet>227</a><span class="kw">impl </span>core::fmt::Display <span class="kw">for </span>MatchError {
<a href=#228 id=228 data-nosnippet>228</a> <span class="kw">fn </span>fmt(<span class="kw-2">&amp;</span><span class="self">self</span>, f: <span class="kw-2">&amp;mut </span>core::fmt::Formatter) -&gt; core::fmt::Result {
<a href=#229 id=229 data-nosnippet>229</a> <span class="kw">match </span><span class="kw-2">*</span><span class="self">self</span>.kind() {
<a href=#230 id=230 data-nosnippet>230</a> MatchErrorKind::InvalidInputAnchored =&gt; {
<a href=#231 id=231 data-nosnippet>231</a> <span class="macro">write!</span>(f, <span class="string">"anchored searches are not supported or enabled"</span>)
<a href=#232 id=232 data-nosnippet>232</a> }
<a href=#233 id=233 data-nosnippet>233</a> MatchErrorKind::InvalidInputUnanchored =&gt; {
<a href=#234 id=234 data-nosnippet>234</a> <span class="macro">write!</span>(f, <span class="string">"unanchored searches are not supported or enabled"</span>)
<a href=#235 id=235 data-nosnippet>235</a> }
<a href=#236 id=236 data-nosnippet>236</a> MatchErrorKind::UnsupportedStream { got } =&gt; {
<a href=#237 id=237 data-nosnippet>237</a> <span class="macro">write!</span>(
<a href=#238 id=238 data-nosnippet>238</a> f,
<a href=#239 id=239 data-nosnippet>239</a> <span class="string">"match kind {:?} does not support stream searching"</span>,
<a href=#240 id=240 data-nosnippet>240</a> got,
<a href=#241 id=241 data-nosnippet>241</a> )
<a href=#242 id=242 data-nosnippet>242</a> }
<a href=#243 id=243 data-nosnippet>243</a> MatchErrorKind::UnsupportedOverlapping { got } =&gt; {
<a href=#244 id=244 data-nosnippet>244</a> <span class="macro">write!</span>(
<a href=#245 id=245 data-nosnippet>245</a> f,
<a href=#246 id=246 data-nosnippet>246</a> <span class="string">"match kind {:?} does not support overlapping searches"</span>,
<a href=#247 id=247 data-nosnippet>247</a> got,
<a href=#248 id=248 data-nosnippet>248</a> )
<a href=#249 id=249 data-nosnippet>249</a> }
<a href=#250 id=250 data-nosnippet>250</a> MatchErrorKind::UnsupportedEmpty =&gt; {
<a href=#251 id=251 data-nosnippet>251</a> <span class="macro">write!</span>(
<a href=#252 id=252 data-nosnippet>252</a> f,
<a href=#253 id=253 data-nosnippet>253</a> <span class="string">"matching with an empty pattern string is not \
<a href=#254 id=254 data-nosnippet>254</a> supported for this operation"</span>,
<a href=#255 id=255 data-nosnippet>255</a> )
<a href=#256 id=256 data-nosnippet>256</a> }
<a href=#257 id=257 data-nosnippet>257</a> }
<a href=#258 id=258 data-nosnippet>258</a> }
<a href=#259 id=259 data-nosnippet>259</a>}
</code></pre></div></section></main></body></html>

View File

@@ -0,0 +1,279 @@
<!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 `/home/newkirk/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/aho-corasick-1.1.4/src/util/int.rs`."><title>int.rs - source</title><script>if(window.location.protocol!=="file:")document.head.insertAdjacentHTML("beforeend","SourceSerif4-Regular-6b053e98.ttf.woff2,FiraSans-Italic-81dc35de.woff2,FiraSans-Regular-0fe48ade.woff2,FiraSans-MediumItalic-ccf7e434.woff2,FiraSans-Medium-e1aa3f0a.woff2,SourceCodePro-Regular-8badfe75.ttf.woff2,SourceCodePro-Semibold-aa29a496.ttf.woff2".split(",").map(f=>`<link rel="preload" as="font" type="font/woff2"href="../../../static.files/${f}">`).join(""))</script><link rel="stylesheet" href="../../../static.files/normalize-9960930a.css"><link rel="stylesheet" href="../../../static.files/rustdoc-ca0dd0c4.css"><meta name="rustdoc-vars" data-root-path="../../../" data-static-root-path="../../../static.files/" data-current-crate="aho_corasick" data-themes="" data-resource-suffix="" data-rustdoc-version="1.93.1 (01f6ddf75 2026-02-11) (Arch Linux rust 1:1.93.1-1)" data-channel="1.93.1" data-search-js="search-9e2438ea.js" data-stringdex-js="stringdex-a3946164.js" data-settings-js="settings-c38705f0.js" ><script src="../../../static.files/storage-e2aeef58.js"></script><script defer src="../../../static.files/src-script-813739b1.js"></script><script defer src="../../../src-files.js"></script><script defer src="../../../static.files/main-a410ff4d.js"></script><noscript><link rel="stylesheet" href="../../../static.files/noscript-263c88ec.css"></noscript><link rel="alternate icon" type="image/png" href="../../../static.files/favicon-32x32-eab170b8.png"><link rel="icon" type="image/svg+xml" href="../../../static.files/favicon-044be391.svg"></head><body class="rustdoc src"><!--[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="src-sidebar-title"><h2>Files</h2></div></nav><div class="sidebar-resizer" title="Drag to resize sidebar"></div><main><section id="main-content" class="content"><div class="main-heading"><h1><div class="sub-heading">aho_corasick/util/</div>int.rs</h1><rustdoc-toolbar></rustdoc-toolbar></div><div class="example-wrap digits-3"><pre class="rust"><code><a href=#1 id=1 data-nosnippet>1</a><span class="doccomment">/*!
<a href=#2 id=2 data-nosnippet>2</a>This module provides several integer oriented traits for converting between
<a href=#3 id=3 data-nosnippet>3</a>both fixed size integers and integers whose size varies based on the target
<a href=#4 id=4 data-nosnippet>4</a>(like `usize`).
<a href=#5 id=5 data-nosnippet>5</a>
<a href=#6 id=6 data-nosnippet>6</a>The main design principle for this module is to centralize all uses of `as`.
<a href=#7 id=7 data-nosnippet>7</a>The thinking here is that `as` makes it very easy to perform accidental lossy
<a href=#8 id=8 data-nosnippet>8</a>conversions, and if we centralize all its uses here under more descriptive
<a href=#9 id=9 data-nosnippet>9</a>higher level operations, its use and correctness becomes easier to audit.
<a href=#10 id=10 data-nosnippet>10</a>
<a href=#11 id=11 data-nosnippet>11</a>This was copied mostly wholesale from `regex-automata`.
<a href=#12 id=12 data-nosnippet>12</a>
<a href=#13 id=13 data-nosnippet>13</a>NOTE: for simplicity, we don't take target pointer width into account here for
<a href=#14 id=14 data-nosnippet>14</a>`usize` conversions. Since we currently only panic in debug mode, skipping the
<a href=#15 id=15 data-nosnippet>15</a>check when it can be proven it isn't needed at compile time doesn't really
<a href=#16 id=16 data-nosnippet>16</a>matter. Now, if we wind up wanting to do as many checks as possible in release
<a href=#17 id=17 data-nosnippet>17</a>mode, then we would want to skip those when we know the conversions are always
<a href=#18 id=18 data-nosnippet>18</a>non-lossy.
<a href=#19 id=19 data-nosnippet>19</a>*/
<a href=#20 id=20 data-nosnippet>20</a>
<a href=#21 id=21 data-nosnippet>21</a></span><span class="comment">// We define a little more than what we need, but I'd rather just have
<a href=#22 id=22 data-nosnippet>22</a>// everything via a consistent and uniform API then have holes.
<a href=#23 id=23 data-nosnippet>23</a></span><span class="attr">#![allow(dead_code)]
<a href=#24 id=24 data-nosnippet>24</a>
<a href=#25 id=25 data-nosnippet>25</a></span><span class="kw">pub</span>(<span class="kw">crate</span>) <span class="kw">trait </span>U8 {
<a href=#26 id=26 data-nosnippet>26</a> <span class="kw">fn </span>as_usize(<span class="self">self</span>) -&gt; usize;
<a href=#27 id=27 data-nosnippet>27</a>}
<a href=#28 id=28 data-nosnippet>28</a>
<a href=#29 id=29 data-nosnippet>29</a><span class="kw">impl </span>U8 <span class="kw">for </span>u8 {
<a href=#30 id=30 data-nosnippet>30</a> <span class="kw">fn </span>as_usize(<span class="self">self</span>) -&gt; usize {
<a href=#31 id=31 data-nosnippet>31</a> usize::from(<span class="self">self</span>)
<a href=#32 id=32 data-nosnippet>32</a> }
<a href=#33 id=33 data-nosnippet>33</a>}
<a href=#34 id=34 data-nosnippet>34</a>
<a href=#35 id=35 data-nosnippet>35</a><span class="kw">pub</span>(<span class="kw">crate</span>) <span class="kw">trait </span>U16 {
<a href=#36 id=36 data-nosnippet>36</a> <span class="kw">fn </span>as_usize(<span class="self">self</span>) -&gt; usize;
<a href=#37 id=37 data-nosnippet>37</a> <span class="kw">fn </span>low_u8(<span class="self">self</span>) -&gt; u8;
<a href=#38 id=38 data-nosnippet>38</a> <span class="kw">fn </span>high_u8(<span class="self">self</span>) -&gt; u8;
<a href=#39 id=39 data-nosnippet>39</a>}
<a href=#40 id=40 data-nosnippet>40</a>
<a href=#41 id=41 data-nosnippet>41</a><span class="kw">impl </span>U16 <span class="kw">for </span>u16 {
<a href=#42 id=42 data-nosnippet>42</a> <span class="kw">fn </span>as_usize(<span class="self">self</span>) -&gt; usize {
<a href=#43 id=43 data-nosnippet>43</a> usize::from(<span class="self">self</span>)
<a href=#44 id=44 data-nosnippet>44</a> }
<a href=#45 id=45 data-nosnippet>45</a>
<a href=#46 id=46 data-nosnippet>46</a> <span class="kw">fn </span>low_u8(<span class="self">self</span>) -&gt; u8 {
<a href=#47 id=47 data-nosnippet>47</a> <span class="self">self </span><span class="kw">as </span>u8
<a href=#48 id=48 data-nosnippet>48</a> }
<a href=#49 id=49 data-nosnippet>49</a>
<a href=#50 id=50 data-nosnippet>50</a> <span class="kw">fn </span>high_u8(<span class="self">self</span>) -&gt; u8 {
<a href=#51 id=51 data-nosnippet>51</a> (<span class="self">self </span>&gt;&gt; <span class="number">8</span>) <span class="kw">as </span>u8
<a href=#52 id=52 data-nosnippet>52</a> }
<a href=#53 id=53 data-nosnippet>53</a>}
<a href=#54 id=54 data-nosnippet>54</a>
<a href=#55 id=55 data-nosnippet>55</a><span class="kw">pub</span>(<span class="kw">crate</span>) <span class="kw">trait </span>U32 {
<a href=#56 id=56 data-nosnippet>56</a> <span class="kw">fn </span>as_usize(<span class="self">self</span>) -&gt; usize;
<a href=#57 id=57 data-nosnippet>57</a> <span class="kw">fn </span>low_u8(<span class="self">self</span>) -&gt; u8;
<a href=#58 id=58 data-nosnippet>58</a> <span class="kw">fn </span>low_u16(<span class="self">self</span>) -&gt; u16;
<a href=#59 id=59 data-nosnippet>59</a> <span class="kw">fn </span>high_u16(<span class="self">self</span>) -&gt; u16;
<a href=#60 id=60 data-nosnippet>60</a>}
<a href=#61 id=61 data-nosnippet>61</a>
<a href=#62 id=62 data-nosnippet>62</a><span class="kw">impl </span>U32 <span class="kw">for </span>u32 {
<a href=#63 id=63 data-nosnippet>63</a> <span class="attr">#[inline]
<a href=#64 id=64 data-nosnippet>64</a> </span><span class="kw">fn </span>as_usize(<span class="self">self</span>) -&gt; usize {
<a href=#65 id=65 data-nosnippet>65</a> <span class="attr">#[cfg(debug_assertions)]
<a href=#66 id=66 data-nosnippet>66</a> </span>{
<a href=#67 id=67 data-nosnippet>67</a> usize::try_from(<span class="self">self</span>).expect(<span class="string">"u32 overflowed usize"</span>)
<a href=#68 id=68 data-nosnippet>68</a> }
<a href=#69 id=69 data-nosnippet>69</a> <span class="attr">#[cfg(not(debug_assertions))]
<a href=#70 id=70 data-nosnippet>70</a> </span>{
<a href=#71 id=71 data-nosnippet>71</a> <span class="self">self </span><span class="kw">as </span>usize
<a href=#72 id=72 data-nosnippet>72</a> }
<a href=#73 id=73 data-nosnippet>73</a> }
<a href=#74 id=74 data-nosnippet>74</a>
<a href=#75 id=75 data-nosnippet>75</a> <span class="kw">fn </span>low_u8(<span class="self">self</span>) -&gt; u8 {
<a href=#76 id=76 data-nosnippet>76</a> <span class="self">self </span><span class="kw">as </span>u8
<a href=#77 id=77 data-nosnippet>77</a> }
<a href=#78 id=78 data-nosnippet>78</a>
<a href=#79 id=79 data-nosnippet>79</a> <span class="kw">fn </span>low_u16(<span class="self">self</span>) -&gt; u16 {
<a href=#80 id=80 data-nosnippet>80</a> <span class="self">self </span><span class="kw">as </span>u16
<a href=#81 id=81 data-nosnippet>81</a> }
<a href=#82 id=82 data-nosnippet>82</a>
<a href=#83 id=83 data-nosnippet>83</a> <span class="kw">fn </span>high_u16(<span class="self">self</span>) -&gt; u16 {
<a href=#84 id=84 data-nosnippet>84</a> (<span class="self">self </span>&gt;&gt; <span class="number">16</span>) <span class="kw">as </span>u16
<a href=#85 id=85 data-nosnippet>85</a> }
<a href=#86 id=86 data-nosnippet>86</a>}
<a href=#87 id=87 data-nosnippet>87</a>
<a href=#88 id=88 data-nosnippet>88</a><span class="kw">pub</span>(<span class="kw">crate</span>) <span class="kw">trait </span>U64 {
<a href=#89 id=89 data-nosnippet>89</a> <span class="kw">fn </span>as_usize(<span class="self">self</span>) -&gt; usize;
<a href=#90 id=90 data-nosnippet>90</a> <span class="kw">fn </span>low_u8(<span class="self">self</span>) -&gt; u8;
<a href=#91 id=91 data-nosnippet>91</a> <span class="kw">fn </span>low_u16(<span class="self">self</span>) -&gt; u16;
<a href=#92 id=92 data-nosnippet>92</a> <span class="kw">fn </span>low_u32(<span class="self">self</span>) -&gt; u32;
<a href=#93 id=93 data-nosnippet>93</a> <span class="kw">fn </span>high_u32(<span class="self">self</span>) -&gt; u32;
<a href=#94 id=94 data-nosnippet>94</a>}
<a href=#95 id=95 data-nosnippet>95</a>
<a href=#96 id=96 data-nosnippet>96</a><span class="kw">impl </span>U64 <span class="kw">for </span>u64 {
<a href=#97 id=97 data-nosnippet>97</a> <span class="kw">fn </span>as_usize(<span class="self">self</span>) -&gt; usize {
<a href=#98 id=98 data-nosnippet>98</a> <span class="attr">#[cfg(debug_assertions)]
<a href=#99 id=99 data-nosnippet>99</a> </span>{
<a href=#100 id=100 data-nosnippet>100</a> usize::try_from(<span class="self">self</span>).expect(<span class="string">"u64 overflowed usize"</span>)
<a href=#101 id=101 data-nosnippet>101</a> }
<a href=#102 id=102 data-nosnippet>102</a> <span class="attr">#[cfg(not(debug_assertions))]
<a href=#103 id=103 data-nosnippet>103</a> </span>{
<a href=#104 id=104 data-nosnippet>104</a> <span class="self">self </span><span class="kw">as </span>usize
<a href=#105 id=105 data-nosnippet>105</a> }
<a href=#106 id=106 data-nosnippet>106</a> }
<a href=#107 id=107 data-nosnippet>107</a>
<a href=#108 id=108 data-nosnippet>108</a> <span class="kw">fn </span>low_u8(<span class="self">self</span>) -&gt; u8 {
<a href=#109 id=109 data-nosnippet>109</a> <span class="self">self </span><span class="kw">as </span>u8
<a href=#110 id=110 data-nosnippet>110</a> }
<a href=#111 id=111 data-nosnippet>111</a>
<a href=#112 id=112 data-nosnippet>112</a> <span class="kw">fn </span>low_u16(<span class="self">self</span>) -&gt; u16 {
<a href=#113 id=113 data-nosnippet>113</a> <span class="self">self </span><span class="kw">as </span>u16
<a href=#114 id=114 data-nosnippet>114</a> }
<a href=#115 id=115 data-nosnippet>115</a>
<a href=#116 id=116 data-nosnippet>116</a> <span class="kw">fn </span>low_u32(<span class="self">self</span>) -&gt; u32 {
<a href=#117 id=117 data-nosnippet>117</a> <span class="self">self </span><span class="kw">as </span>u32
<a href=#118 id=118 data-nosnippet>118</a> }
<a href=#119 id=119 data-nosnippet>119</a>
<a href=#120 id=120 data-nosnippet>120</a> <span class="kw">fn </span>high_u32(<span class="self">self</span>) -&gt; u32 {
<a href=#121 id=121 data-nosnippet>121</a> (<span class="self">self </span>&gt;&gt; <span class="number">32</span>) <span class="kw">as </span>u32
<a href=#122 id=122 data-nosnippet>122</a> }
<a href=#123 id=123 data-nosnippet>123</a>}
<a href=#124 id=124 data-nosnippet>124</a>
<a href=#125 id=125 data-nosnippet>125</a><span class="kw">pub</span>(<span class="kw">crate</span>) <span class="kw">trait </span>I8 {
<a href=#126 id=126 data-nosnippet>126</a> <span class="kw">fn </span>as_usize(<span class="self">self</span>) -&gt; usize;
<a href=#127 id=127 data-nosnippet>127</a> <span class="kw">fn </span>to_bits(<span class="self">self</span>) -&gt; u8;
<a href=#128 id=128 data-nosnippet>128</a> <span class="kw">fn </span>from_bits(n: u8) -&gt; i8;
<a href=#129 id=129 data-nosnippet>129</a>}
<a href=#130 id=130 data-nosnippet>130</a>
<a href=#131 id=131 data-nosnippet>131</a><span class="kw">impl </span>I8 <span class="kw">for </span>i8 {
<a href=#132 id=132 data-nosnippet>132</a> <span class="kw">fn </span>as_usize(<span class="self">self</span>) -&gt; usize {
<a href=#133 id=133 data-nosnippet>133</a> <span class="attr">#[cfg(debug_assertions)]
<a href=#134 id=134 data-nosnippet>134</a> </span>{
<a href=#135 id=135 data-nosnippet>135</a> usize::try_from(<span class="self">self</span>).expect(<span class="string">"i8 overflowed usize"</span>)
<a href=#136 id=136 data-nosnippet>136</a> }
<a href=#137 id=137 data-nosnippet>137</a> <span class="attr">#[cfg(not(debug_assertions))]
<a href=#138 id=138 data-nosnippet>138</a> </span>{
<a href=#139 id=139 data-nosnippet>139</a> <span class="self">self </span><span class="kw">as </span>usize
<a href=#140 id=140 data-nosnippet>140</a> }
<a href=#141 id=141 data-nosnippet>141</a> }
<a href=#142 id=142 data-nosnippet>142</a>
<a href=#143 id=143 data-nosnippet>143</a> <span class="kw">fn </span>to_bits(<span class="self">self</span>) -&gt; u8 {
<a href=#144 id=144 data-nosnippet>144</a> <span class="self">self </span><span class="kw">as </span>u8
<a href=#145 id=145 data-nosnippet>145</a> }
<a href=#146 id=146 data-nosnippet>146</a>
<a href=#147 id=147 data-nosnippet>147</a> <span class="kw">fn </span>from_bits(n: u8) -&gt; i8 {
<a href=#148 id=148 data-nosnippet>148</a> n <span class="kw">as </span>i8
<a href=#149 id=149 data-nosnippet>149</a> }
<a href=#150 id=150 data-nosnippet>150</a>}
<a href=#151 id=151 data-nosnippet>151</a>
<a href=#152 id=152 data-nosnippet>152</a><span class="kw">pub</span>(<span class="kw">crate</span>) <span class="kw">trait </span>I32 {
<a href=#153 id=153 data-nosnippet>153</a> <span class="kw">fn </span>as_usize(<span class="self">self</span>) -&gt; usize;
<a href=#154 id=154 data-nosnippet>154</a> <span class="kw">fn </span>to_bits(<span class="self">self</span>) -&gt; u32;
<a href=#155 id=155 data-nosnippet>155</a> <span class="kw">fn </span>from_bits(n: u32) -&gt; i32;
<a href=#156 id=156 data-nosnippet>156</a>}
<a href=#157 id=157 data-nosnippet>157</a>
<a href=#158 id=158 data-nosnippet>158</a><span class="kw">impl </span>I32 <span class="kw">for </span>i32 {
<a href=#159 id=159 data-nosnippet>159</a> <span class="kw">fn </span>as_usize(<span class="self">self</span>) -&gt; usize {
<a href=#160 id=160 data-nosnippet>160</a> <span class="attr">#[cfg(debug_assertions)]
<a href=#161 id=161 data-nosnippet>161</a> </span>{
<a href=#162 id=162 data-nosnippet>162</a> usize::try_from(<span class="self">self</span>).expect(<span class="string">"i32 overflowed usize"</span>)
<a href=#163 id=163 data-nosnippet>163</a> }
<a href=#164 id=164 data-nosnippet>164</a> <span class="attr">#[cfg(not(debug_assertions))]
<a href=#165 id=165 data-nosnippet>165</a> </span>{
<a href=#166 id=166 data-nosnippet>166</a> <span class="self">self </span><span class="kw">as </span>usize
<a href=#167 id=167 data-nosnippet>167</a> }
<a href=#168 id=168 data-nosnippet>168</a> }
<a href=#169 id=169 data-nosnippet>169</a>
<a href=#170 id=170 data-nosnippet>170</a> <span class="kw">fn </span>to_bits(<span class="self">self</span>) -&gt; u32 {
<a href=#171 id=171 data-nosnippet>171</a> <span class="self">self </span><span class="kw">as </span>u32
<a href=#172 id=172 data-nosnippet>172</a> }
<a href=#173 id=173 data-nosnippet>173</a>
<a href=#174 id=174 data-nosnippet>174</a> <span class="kw">fn </span>from_bits(n: u32) -&gt; i32 {
<a href=#175 id=175 data-nosnippet>175</a> n <span class="kw">as </span>i32
<a href=#176 id=176 data-nosnippet>176</a> }
<a href=#177 id=177 data-nosnippet>177</a>}
<a href=#178 id=178 data-nosnippet>178</a>
<a href=#179 id=179 data-nosnippet>179</a><span class="kw">pub</span>(<span class="kw">crate</span>) <span class="kw">trait </span>I64 {
<a href=#180 id=180 data-nosnippet>180</a> <span class="kw">fn </span>as_usize(<span class="self">self</span>) -&gt; usize;
<a href=#181 id=181 data-nosnippet>181</a> <span class="kw">fn </span>to_bits(<span class="self">self</span>) -&gt; u64;
<a href=#182 id=182 data-nosnippet>182</a> <span class="kw">fn </span>from_bits(n: u64) -&gt; i64;
<a href=#183 id=183 data-nosnippet>183</a>}
<a href=#184 id=184 data-nosnippet>184</a>
<a href=#185 id=185 data-nosnippet>185</a><span class="kw">impl </span>I64 <span class="kw">for </span>i64 {
<a href=#186 id=186 data-nosnippet>186</a> <span class="kw">fn </span>as_usize(<span class="self">self</span>) -&gt; usize {
<a href=#187 id=187 data-nosnippet>187</a> <span class="attr">#[cfg(debug_assertions)]
<a href=#188 id=188 data-nosnippet>188</a> </span>{
<a href=#189 id=189 data-nosnippet>189</a> usize::try_from(<span class="self">self</span>).expect(<span class="string">"i64 overflowed usize"</span>)
<a href=#190 id=190 data-nosnippet>190</a> }
<a href=#191 id=191 data-nosnippet>191</a> <span class="attr">#[cfg(not(debug_assertions))]
<a href=#192 id=192 data-nosnippet>192</a> </span>{
<a href=#193 id=193 data-nosnippet>193</a> <span class="self">self </span><span class="kw">as </span>usize
<a href=#194 id=194 data-nosnippet>194</a> }
<a href=#195 id=195 data-nosnippet>195</a> }
<a href=#196 id=196 data-nosnippet>196</a>
<a href=#197 id=197 data-nosnippet>197</a> <span class="kw">fn </span>to_bits(<span class="self">self</span>) -&gt; u64 {
<a href=#198 id=198 data-nosnippet>198</a> <span class="self">self </span><span class="kw">as </span>u64
<a href=#199 id=199 data-nosnippet>199</a> }
<a href=#200 id=200 data-nosnippet>200</a>
<a href=#201 id=201 data-nosnippet>201</a> <span class="kw">fn </span>from_bits(n: u64) -&gt; i64 {
<a href=#202 id=202 data-nosnippet>202</a> n <span class="kw">as </span>i64
<a href=#203 id=203 data-nosnippet>203</a> }
<a href=#204 id=204 data-nosnippet>204</a>}
<a href=#205 id=205 data-nosnippet>205</a>
<a href=#206 id=206 data-nosnippet>206</a><span class="kw">pub</span>(<span class="kw">crate</span>) <span class="kw">trait </span>Usize {
<a href=#207 id=207 data-nosnippet>207</a> <span class="kw">fn </span>as_u8(<span class="self">self</span>) -&gt; u8;
<a href=#208 id=208 data-nosnippet>208</a> <span class="kw">fn </span>as_u16(<span class="self">self</span>) -&gt; u16;
<a href=#209 id=209 data-nosnippet>209</a> <span class="kw">fn </span>as_u32(<span class="self">self</span>) -&gt; u32;
<a href=#210 id=210 data-nosnippet>210</a> <span class="kw">fn </span>as_u64(<span class="self">self</span>) -&gt; u64;
<a href=#211 id=211 data-nosnippet>211</a>}
<a href=#212 id=212 data-nosnippet>212</a>
<a href=#213 id=213 data-nosnippet>213</a><span class="kw">impl </span>Usize <span class="kw">for </span>usize {
<a href=#214 id=214 data-nosnippet>214</a> <span class="kw">fn </span>as_u8(<span class="self">self</span>) -&gt; u8 {
<a href=#215 id=215 data-nosnippet>215</a> <span class="attr">#[cfg(debug_assertions)]
<a href=#216 id=216 data-nosnippet>216</a> </span>{
<a href=#217 id=217 data-nosnippet>217</a> u8::try_from(<span class="self">self</span>).expect(<span class="string">"usize overflowed u8"</span>)
<a href=#218 id=218 data-nosnippet>218</a> }
<a href=#219 id=219 data-nosnippet>219</a> <span class="attr">#[cfg(not(debug_assertions))]
<a href=#220 id=220 data-nosnippet>220</a> </span>{
<a href=#221 id=221 data-nosnippet>221</a> <span class="self">self </span><span class="kw">as </span>u8
<a href=#222 id=222 data-nosnippet>222</a> }
<a href=#223 id=223 data-nosnippet>223</a> }
<a href=#224 id=224 data-nosnippet>224</a>
<a href=#225 id=225 data-nosnippet>225</a> <span class="kw">fn </span>as_u16(<span class="self">self</span>) -&gt; u16 {
<a href=#226 id=226 data-nosnippet>226</a> <span class="attr">#[cfg(debug_assertions)]
<a href=#227 id=227 data-nosnippet>227</a> </span>{
<a href=#228 id=228 data-nosnippet>228</a> u16::try_from(<span class="self">self</span>).expect(<span class="string">"usize overflowed u16"</span>)
<a href=#229 id=229 data-nosnippet>229</a> }
<a href=#230 id=230 data-nosnippet>230</a> <span class="attr">#[cfg(not(debug_assertions))]
<a href=#231 id=231 data-nosnippet>231</a> </span>{
<a href=#232 id=232 data-nosnippet>232</a> <span class="self">self </span><span class="kw">as </span>u16
<a href=#233 id=233 data-nosnippet>233</a> }
<a href=#234 id=234 data-nosnippet>234</a> }
<a href=#235 id=235 data-nosnippet>235</a>
<a href=#236 id=236 data-nosnippet>236</a> <span class="kw">fn </span>as_u32(<span class="self">self</span>) -&gt; u32 {
<a href=#237 id=237 data-nosnippet>237</a> <span class="attr">#[cfg(debug_assertions)]
<a href=#238 id=238 data-nosnippet>238</a> </span>{
<a href=#239 id=239 data-nosnippet>239</a> u32::try_from(<span class="self">self</span>).expect(<span class="string">"usize overflowed u32"</span>)
<a href=#240 id=240 data-nosnippet>240</a> }
<a href=#241 id=241 data-nosnippet>241</a> <span class="attr">#[cfg(not(debug_assertions))]
<a href=#242 id=242 data-nosnippet>242</a> </span>{
<a href=#243 id=243 data-nosnippet>243</a> <span class="self">self </span><span class="kw">as </span>u32
<a href=#244 id=244 data-nosnippet>244</a> }
<a href=#245 id=245 data-nosnippet>245</a> }
<a href=#246 id=246 data-nosnippet>246</a>
<a href=#247 id=247 data-nosnippet>247</a> <span class="kw">fn </span>as_u64(<span class="self">self</span>) -&gt; u64 {
<a href=#248 id=248 data-nosnippet>248</a> <span class="attr">#[cfg(debug_assertions)]
<a href=#249 id=249 data-nosnippet>249</a> </span>{
<a href=#250 id=250 data-nosnippet>250</a> u64::try_from(<span class="self">self</span>).expect(<span class="string">"usize overflowed u64"</span>)
<a href=#251 id=251 data-nosnippet>251</a> }
<a href=#252 id=252 data-nosnippet>252</a> <span class="attr">#[cfg(not(debug_assertions))]
<a href=#253 id=253 data-nosnippet>253</a> </span>{
<a href=#254 id=254 data-nosnippet>254</a> <span class="self">self </span><span class="kw">as </span>u64
<a href=#255 id=255 data-nosnippet>255</a> }
<a href=#256 id=256 data-nosnippet>256</a> }
<a href=#257 id=257 data-nosnippet>257</a>}
<a href=#258 id=258 data-nosnippet>258</a>
<a href=#259 id=259 data-nosnippet>259</a><span class="comment">// Pointers aren't integers, but we convert pointers to integers to perform
<a href=#260 id=260 data-nosnippet>260</a>// offset arithmetic in some places. (And no, we don't convert the integers
<a href=#261 id=261 data-nosnippet>261</a>// back to pointers.) So add 'as_usize' conversions here too for completeness.
<a href=#262 id=262 data-nosnippet>262</a>//
<a href=#263 id=263 data-nosnippet>263</a>// These 'as' casts are actually okay because they're always non-lossy. But the
<a href=#264 id=264 data-nosnippet>264</a>// idea here is to just try and remove as much 'as' as possible, particularly
<a href=#265 id=265 data-nosnippet>265</a>// in this crate where we are being really paranoid about offsets and making
<a href=#266 id=266 data-nosnippet>266</a>// sure we don't panic on inputs that might be untrusted. This way, the 'as'
<a href=#267 id=267 data-nosnippet>267</a>// casts become easier to audit if they're all in one place, even when some of
<a href=#268 id=268 data-nosnippet>268</a>// them are actually okay 100% of the time.
<a href=#269 id=269 data-nosnippet>269</a>
<a href=#270 id=270 data-nosnippet>270</a></span><span class="kw">pub</span>(<span class="kw">crate</span>) <span class="kw">trait </span>Pointer {
<a href=#271 id=271 data-nosnippet>271</a> <span class="kw">fn </span>as_usize(<span class="self">self</span>) -&gt; usize;
<a href=#272 id=272 data-nosnippet>272</a>}
<a href=#273 id=273 data-nosnippet>273</a>
<a href=#274 id=274 data-nosnippet>274</a><span class="kw">impl</span>&lt;T&gt; Pointer <span class="kw">for </span><span class="kw-2">*const </span>T {
<a href=#275 id=275 data-nosnippet>275</a> <span class="kw">fn </span>as_usize(<span class="self">self</span>) -&gt; usize {
<a href=#276 id=276 data-nosnippet>276</a> <span class="self">self </span><span class="kw">as </span>usize
<a href=#277 id=277 data-nosnippet>277</a> }
<a href=#278 id=278 data-nosnippet>278</a>}
</code></pre></div></section></main></body></html>

View File

@@ -0,0 +1,13 @@
<!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 `/home/newkirk/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/aho-corasick-1.1.4/src/util/mod.rs`."><title>mod.rs - source</title><script>if(window.location.protocol!=="file:")document.head.insertAdjacentHTML("beforeend","SourceSerif4-Regular-6b053e98.ttf.woff2,FiraSans-Italic-81dc35de.woff2,FiraSans-Regular-0fe48ade.woff2,FiraSans-MediumItalic-ccf7e434.woff2,FiraSans-Medium-e1aa3f0a.woff2,SourceCodePro-Regular-8badfe75.ttf.woff2,SourceCodePro-Semibold-aa29a496.ttf.woff2".split(",").map(f=>`<link rel="preload" as="font" type="font/woff2"href="../../../static.files/${f}">`).join(""))</script><link rel="stylesheet" href="../../../static.files/normalize-9960930a.css"><link rel="stylesheet" href="../../../static.files/rustdoc-ca0dd0c4.css"><meta name="rustdoc-vars" data-root-path="../../../" data-static-root-path="../../../static.files/" data-current-crate="aho_corasick" data-themes="" data-resource-suffix="" data-rustdoc-version="1.93.1 (01f6ddf75 2026-02-11) (Arch Linux rust 1:1.93.1-1)" data-channel="1.93.1" data-search-js="search-9e2438ea.js" data-stringdex-js="stringdex-a3946164.js" data-settings-js="settings-c38705f0.js" ><script src="../../../static.files/storage-e2aeef58.js"></script><script defer src="../../../static.files/src-script-813739b1.js"></script><script defer src="../../../src-files.js"></script><script defer src="../../../static.files/main-a410ff4d.js"></script><noscript><link rel="stylesheet" href="../../../static.files/noscript-263c88ec.css"></noscript><link rel="alternate icon" type="image/png" href="../../../static.files/favicon-32x32-eab170b8.png"><link rel="icon" type="image/svg+xml" href="../../../static.files/favicon-044be391.svg"></head><body class="rustdoc src"><!--[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="src-sidebar-title"><h2>Files</h2></div></nav><div class="sidebar-resizer" title="Drag to resize sidebar"></div><main><section id="main-content" class="content"><div class="main-heading"><h1><div class="sub-heading">aho_corasick/util/</div>mod.rs</h1><rustdoc-toolbar></rustdoc-toolbar></div><div class="example-wrap digits-2"><pre class="rust"><code><a href=#1 id=1 data-nosnippet>1</a><span class="kw">pub</span>(<span class="kw">crate</span>) <span class="kw">mod </span>alphabet;
<a href=#2 id=2 data-nosnippet>2</a><span class="attr">#[cfg(feature = <span class="string">"std"</span>)]
<a href=#3 id=3 data-nosnippet>3</a></span><span class="kw">pub</span>(<span class="kw">crate</span>) <span class="kw">mod </span>buffer;
<a href=#4 id=4 data-nosnippet>4</a><span class="kw">pub</span>(<span class="kw">crate</span>) <span class="kw">mod </span>byte_frequencies;
<a href=#5 id=5 data-nosnippet>5</a><span class="kw">pub</span>(<span class="kw">crate</span>) <span class="kw">mod </span>debug;
<a href=#6 id=6 data-nosnippet>6</a><span class="kw">pub</span>(<span class="kw">crate</span>) <span class="kw">mod </span>error;
<a href=#7 id=7 data-nosnippet>7</a><span class="kw">pub</span>(<span class="kw">crate</span>) <span class="kw">mod </span>int;
<a href=#8 id=8 data-nosnippet>8</a><span class="kw">pub</span>(<span class="kw">crate</span>) <span class="kw">mod </span>prefilter;
<a href=#9 id=9 data-nosnippet>9</a><span class="kw">pub</span>(<span class="kw">crate</span>) <span class="kw">mod </span>primitives;
<a href=#10 id=10 data-nosnippet>10</a><span class="kw">pub</span>(<span class="kw">crate</span>) <span class="kw">mod </span>remapper;
<a href=#11 id=11 data-nosnippet>11</a><span class="kw">pub</span>(<span class="kw">crate</span>) <span class="kw">mod </span>search;
<a href=#12 id=12 data-nosnippet>12</a><span class="kw">pub</span>(<span class="kw">crate</span>) <span class="kw">mod </span>special;
</code></pre></div></section></main></body></html>

View File

@@ -0,0 +1,925 @@
<!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 `/home/newkirk/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/aho-corasick-1.1.4/src/util/prefilter.rs`."><title>prefilter.rs - source</title><script>if(window.location.protocol!=="file:")document.head.insertAdjacentHTML("beforeend","SourceSerif4-Regular-6b053e98.ttf.woff2,FiraSans-Italic-81dc35de.woff2,FiraSans-Regular-0fe48ade.woff2,FiraSans-MediumItalic-ccf7e434.woff2,FiraSans-Medium-e1aa3f0a.woff2,SourceCodePro-Regular-8badfe75.ttf.woff2,SourceCodePro-Semibold-aa29a496.ttf.woff2".split(",").map(f=>`<link rel="preload" as="font" type="font/woff2"href="../../../static.files/${f}">`).join(""))</script><link rel="stylesheet" href="../../../static.files/normalize-9960930a.css"><link rel="stylesheet" href="../../../static.files/rustdoc-ca0dd0c4.css"><meta name="rustdoc-vars" data-root-path="../../../" data-static-root-path="../../../static.files/" data-current-crate="aho_corasick" data-themes="" data-resource-suffix="" data-rustdoc-version="1.93.1 (01f6ddf75 2026-02-11) (Arch Linux rust 1:1.93.1-1)" data-channel="1.93.1" data-search-js="search-9e2438ea.js" data-stringdex-js="stringdex-a3946164.js" data-settings-js="settings-c38705f0.js" ><script src="../../../static.files/storage-e2aeef58.js"></script><script defer src="../../../static.files/src-script-813739b1.js"></script><script defer src="../../../src-files.js"></script><script defer src="../../../static.files/main-a410ff4d.js"></script><noscript><link rel="stylesheet" href="../../../static.files/noscript-263c88ec.css"></noscript><link rel="alternate icon" type="image/png" href="../../../static.files/favicon-32x32-eab170b8.png"><link rel="icon" type="image/svg+xml" href="../../../static.files/favicon-044be391.svg"></head><body class="rustdoc src"><!--[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="src-sidebar-title"><h2>Files</h2></div></nav><div class="sidebar-resizer" title="Drag to resize sidebar"></div><main><section id="main-content" class="content"><div class="main-heading"><h1><div class="sub-heading">aho_corasick/util/</div>prefilter.rs</h1><rustdoc-toolbar></rustdoc-toolbar></div><div class="example-wrap digits-3"><pre class="rust"><code><a href=#1 id=1 data-nosnippet>1</a><span class="kw">use </span>core::{
<a href=#2 id=2 data-nosnippet>2</a> cmp,
<a href=#3 id=3 data-nosnippet>3</a> fmt::Debug,
<a href=#4 id=4 data-nosnippet>4</a> panic::{RefUnwindSafe, UnwindSafe},
<a href=#5 id=5 data-nosnippet>5</a> u8,
<a href=#6 id=6 data-nosnippet>6</a>};
<a href=#7 id=7 data-nosnippet>7</a>
<a href=#8 id=8 data-nosnippet>8</a><span class="kw">use </span>alloc::{sync::Arc, vec, vec::Vec};
<a href=#9 id=9 data-nosnippet>9</a>
<a href=#10 id=10 data-nosnippet>10</a><span class="kw">use crate</span>::{
<a href=#11 id=11 data-nosnippet>11</a> packed,
<a href=#12 id=12 data-nosnippet>12</a> util::{
<a href=#13 id=13 data-nosnippet>13</a> alphabet::ByteSet,
<a href=#14 id=14 data-nosnippet>14</a> search::{Match, MatchKind, Span},
<a href=#15 id=15 data-nosnippet>15</a> },
<a href=#16 id=16 data-nosnippet>16</a>};
<a href=#17 id=17 data-nosnippet>17</a>
<a href=#18 id=18 data-nosnippet>18</a><span class="doccomment">/// A prefilter for accelerating a search.
<a href=#19 id=19 data-nosnippet>19</a>///
<a href=#20 id=20 data-nosnippet>20</a>/// This crate uses prefilters in the core search implementations to accelerate
<a href=#21 id=21 data-nosnippet>21</a>/// common cases. They typically only apply to cases where there are a small
<a href=#22 id=22 data-nosnippet>22</a>/// number of patterns (less than 100 or so), but when they do, thoughput can
<a href=#23 id=23 data-nosnippet>23</a>/// be boosted considerably, perhaps by an order of magnitude. When a prefilter
<a href=#24 id=24 data-nosnippet>24</a>/// is active, it is used whenever a search enters an automaton's start state.
<a href=#25 id=25 data-nosnippet>25</a>///
<a href=#26 id=26 data-nosnippet>26</a>/// Currently, prefilters cannot be constructed by
<a href=#27 id=27 data-nosnippet>27</a>/// callers. A `Prefilter` can only be accessed via the
<a href=#28 id=28 data-nosnippet>28</a>/// [`Automaton::prefilter`](crate::automaton::Automaton::prefilter)
<a href=#29 id=29 data-nosnippet>29</a>/// method and used to execute a search. In other words, a prefilter can be
<a href=#30 id=30 data-nosnippet>30</a>/// used to optimize your own search implementation if necessary, but cannot do
<a href=#31 id=31 data-nosnippet>31</a>/// much else. If you have a use case for more APIs, please submit an issue.
<a href=#32 id=32 data-nosnippet>32</a></span><span class="attr">#[derive(Clone, Debug)]
<a href=#33 id=33 data-nosnippet>33</a></span><span class="kw">pub struct </span>Prefilter {
<a href=#34 id=34 data-nosnippet>34</a> finder: Arc&lt;<span class="kw">dyn </span>PrefilterI&gt;,
<a href=#35 id=35 data-nosnippet>35</a> memory_usage: usize,
<a href=#36 id=36 data-nosnippet>36</a>}
<a href=#37 id=37 data-nosnippet>37</a>
<a href=#38 id=38 data-nosnippet>38</a><span class="kw">impl </span>Prefilter {
<a href=#39 id=39 data-nosnippet>39</a> <span class="doccomment">/// Execute a search in the haystack within the span given. If a match or
<a href=#40 id=40 data-nosnippet>40</a> /// a possible match is returned, then it is guaranteed to occur within
<a href=#41 id=41 data-nosnippet>41</a> /// the bounds of the span.
<a href=#42 id=42 data-nosnippet>42</a> ///
<a href=#43 id=43 data-nosnippet>43</a> /// If the span provided is invalid for the given haystack, then behavior
<a href=#44 id=44 data-nosnippet>44</a> /// is unspecified.
<a href=#45 id=45 data-nosnippet>45</a> </span><span class="attr">#[inline]
<a href=#46 id=46 data-nosnippet>46</a> </span><span class="kw">pub fn </span>find_in(<span class="kw-2">&amp;</span><span class="self">self</span>, haystack: <span class="kw-2">&amp;</span>[u8], span: Span) -&gt; Candidate {
<a href=#47 id=47 data-nosnippet>47</a> <span class="self">self</span>.finder.find_in(haystack, span)
<a href=#48 id=48 data-nosnippet>48</a> }
<a href=#49 id=49 data-nosnippet>49</a>
<a href=#50 id=50 data-nosnippet>50</a> <span class="attr">#[inline]
<a href=#51 id=51 data-nosnippet>51</a> </span><span class="kw">pub</span>(<span class="kw">crate</span>) <span class="kw">fn </span>memory_usage(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; usize {
<a href=#52 id=52 data-nosnippet>52</a> <span class="self">self</span>.memory_usage
<a href=#53 id=53 data-nosnippet>53</a> }
<a href=#54 id=54 data-nosnippet>54</a>}
<a href=#55 id=55 data-nosnippet>55</a>
<a href=#56 id=56 data-nosnippet>56</a><span class="doccomment">/// A candidate is the result of running a prefilter on a haystack at a
<a href=#57 id=57 data-nosnippet>57</a>/// particular position.
<a href=#58 id=58 data-nosnippet>58</a>///
<a href=#59 id=59 data-nosnippet>59</a>/// The result is either no match, a confirmed match or a possible match.
<a href=#60 id=60 data-nosnippet>60</a>///
<a href=#61 id=61 data-nosnippet>61</a>/// When no match is returned, the prefilter is guaranteeing that no possible
<a href=#62 id=62 data-nosnippet>62</a>/// match can be found in the haystack, and the caller may trust this. That is,
<a href=#63 id=63 data-nosnippet>63</a>/// all correct prefilters must never report false negatives.
<a href=#64 id=64 data-nosnippet>64</a>///
<a href=#65 id=65 data-nosnippet>65</a>/// In some cases, a prefilter can confirm a match very quickly, in which case,
<a href=#66 id=66 data-nosnippet>66</a>/// the caller may use this to stop what it's doing and report the match. In
<a href=#67 id=67 data-nosnippet>67</a>/// this case, prefilter implementations must never report a false positive.
<a href=#68 id=68 data-nosnippet>68</a>/// In other cases, the prefilter can only report a potential match, in which
<a href=#69 id=69 data-nosnippet>69</a>/// case the callers must attempt to confirm the match. In this case, prefilter
<a href=#70 id=70 data-nosnippet>70</a>/// implementations are permitted to return false positives.
<a href=#71 id=71 data-nosnippet>71</a></span><span class="attr">#[derive(Clone, Debug)]
<a href=#72 id=72 data-nosnippet>72</a></span><span class="kw">pub enum </span>Candidate {
<a href=#73 id=73 data-nosnippet>73</a> <span class="doccomment">/// No match was found. Since false negatives are not possible, this means
<a href=#74 id=74 data-nosnippet>74</a> /// the search can quit as it is guaranteed not to find another match.
<a href=#75 id=75 data-nosnippet>75</a> </span><span class="prelude-val">None</span>,
<a href=#76 id=76 data-nosnippet>76</a> <span class="doccomment">/// A confirmed match was found. Callers do not need to confirm it.
<a href=#77 id=77 data-nosnippet>77</a> </span>Match(Match),
<a href=#78 id=78 data-nosnippet>78</a> <span class="doccomment">/// The start of a possible match was found. Callers must confirm it before
<a href=#79 id=79 data-nosnippet>79</a> /// reporting it as a match.
<a href=#80 id=80 data-nosnippet>80</a> </span>PossibleStartOfMatch(usize),
<a href=#81 id=81 data-nosnippet>81</a>}
<a href=#82 id=82 data-nosnippet>82</a>
<a href=#83 id=83 data-nosnippet>83</a><span class="kw">impl </span>Candidate {
<a href=#84 id=84 data-nosnippet>84</a> <span class="doccomment">/// Convert this candidate into an option. This is useful when callers
<a href=#85 id=85 data-nosnippet>85</a> /// do not distinguish between true positives and false positives (i.e.,
<a href=#86 id=86 data-nosnippet>86</a> /// the caller must always confirm the match).
<a href=#87 id=87 data-nosnippet>87</a> </span><span class="kw">pub fn </span>into_option(<span class="self">self</span>) -&gt; <span class="prelude-ty">Option</span>&lt;usize&gt; {
<a href=#88 id=88 data-nosnippet>88</a> <span class="kw">match </span><span class="self">self </span>{
<a href=#89 id=89 data-nosnippet>89</a> Candidate::None =&gt; <span class="prelude-val">None</span>,
<a href=#90 id=90 data-nosnippet>90</a> Candidate::Match(<span class="kw-2">ref </span>m) =&gt; <span class="prelude-val">Some</span>(m.start()),
<a href=#91 id=91 data-nosnippet>91</a> Candidate::PossibleStartOfMatch(start) =&gt; <span class="prelude-val">Some</span>(start),
<a href=#92 id=92 data-nosnippet>92</a> }
<a href=#93 id=93 data-nosnippet>93</a> }
<a href=#94 id=94 data-nosnippet>94</a>}
<a href=#95 id=95 data-nosnippet>95</a>
<a href=#96 id=96 data-nosnippet>96</a><span class="doccomment">/// A prefilter describes the behavior of fast literal scanners for quickly
<a href=#97 id=97 data-nosnippet>97</a>/// skipping past bytes in the haystack that we know cannot possibly
<a href=#98 id=98 data-nosnippet>98</a>/// participate in a match.
<a href=#99 id=99 data-nosnippet>99</a></span><span class="kw">trait </span>PrefilterI:
<a href=#100 id=100 data-nosnippet>100</a> Send + Sync + RefUnwindSafe + UnwindSafe + Debug + <span class="lifetime">'static
<a href=#101 id=101 data-nosnippet>101</a></span>{
<a href=#102 id=102 data-nosnippet>102</a> <span class="doccomment">/// Returns the next possible match candidate. This may yield false
<a href=#103 id=103 data-nosnippet>103</a> /// positives, so callers must confirm a match starting at the position
<a href=#104 id=104 data-nosnippet>104</a> /// returned. This, however, must never produce false negatives. That is,
<a href=#105 id=105 data-nosnippet>105</a> /// this must, at minimum, return the starting position of the next match
<a href=#106 id=106 data-nosnippet>106</a> /// in the given haystack after or at the given position.
<a href=#107 id=107 data-nosnippet>107</a> </span><span class="kw">fn </span>find_in(<span class="kw-2">&amp;</span><span class="self">self</span>, haystack: <span class="kw-2">&amp;</span>[u8], span: Span) -&gt; Candidate;
<a href=#108 id=108 data-nosnippet>108</a>}
<a href=#109 id=109 data-nosnippet>109</a>
<a href=#110 id=110 data-nosnippet>110</a><span class="kw">impl</span>&lt;P: PrefilterI + <span class="question-mark">?</span>Sized&gt; PrefilterI <span class="kw">for </span>Arc&lt;P&gt; {
<a href=#111 id=111 data-nosnippet>111</a> <span class="attr">#[inline(always)]
<a href=#112 id=112 data-nosnippet>112</a> </span><span class="kw">fn </span>find_in(<span class="kw-2">&amp;</span><span class="self">self</span>, haystack: <span class="kw-2">&amp;</span>[u8], span: Span) -&gt; Candidate {
<a href=#113 id=113 data-nosnippet>113</a> (<span class="kw-2">**</span><span class="self">self</span>).find_in(haystack, span)
<a href=#114 id=114 data-nosnippet>114</a> }
<a href=#115 id=115 data-nosnippet>115</a>}
<a href=#116 id=116 data-nosnippet>116</a>
<a href=#117 id=117 data-nosnippet>117</a><span class="doccomment">/// A builder for constructing the best possible prefilter. When constructed,
<a href=#118 id=118 data-nosnippet>118</a>/// this builder will heuristically select the best prefilter it can build,
<a href=#119 id=119 data-nosnippet>119</a>/// if any, and discard the rest.
<a href=#120 id=120 data-nosnippet>120</a></span><span class="attr">#[derive(Debug)]
<a href=#121 id=121 data-nosnippet>121</a></span><span class="kw">pub</span>(<span class="kw">crate</span>) <span class="kw">struct </span>Builder {
<a href=#122 id=122 data-nosnippet>122</a> count: usize,
<a href=#123 id=123 data-nosnippet>123</a> ascii_case_insensitive: bool,
<a href=#124 id=124 data-nosnippet>124</a> start_bytes: StartBytesBuilder,
<a href=#125 id=125 data-nosnippet>125</a> rare_bytes: RareBytesBuilder,
<a href=#126 id=126 data-nosnippet>126</a> memmem: MemmemBuilder,
<a href=#127 id=127 data-nosnippet>127</a> packed: <span class="prelude-ty">Option</span>&lt;packed::Builder&gt;,
<a href=#128 id=128 data-nosnippet>128</a> <span class="comment">// If we run across a condition that suggests we shouldn't use a prefilter
<a href=#129 id=129 data-nosnippet>129</a> // at all (like an empty pattern), then disable prefilters entirely.
<a href=#130 id=130 data-nosnippet>130</a> </span>enabled: bool,
<a href=#131 id=131 data-nosnippet>131</a>}
<a href=#132 id=132 data-nosnippet>132</a>
<a href=#133 id=133 data-nosnippet>133</a><span class="kw">impl </span>Builder {
<a href=#134 id=134 data-nosnippet>134</a> <span class="doccomment">/// Create a new builder for constructing the best possible prefilter.
<a href=#135 id=135 data-nosnippet>135</a> </span><span class="kw">pub</span>(<span class="kw">crate</span>) <span class="kw">fn </span>new(kind: MatchKind) -&gt; Builder {
<a href=#136 id=136 data-nosnippet>136</a> <span class="kw">let </span>pbuilder = kind
<a href=#137 id=137 data-nosnippet>137</a> .as_packed()
<a href=#138 id=138 data-nosnippet>138</a> .map(|kind| packed::Config::new().match_kind(kind).builder());
<a href=#139 id=139 data-nosnippet>139</a> Builder {
<a href=#140 id=140 data-nosnippet>140</a> count: <span class="number">0</span>,
<a href=#141 id=141 data-nosnippet>141</a> ascii_case_insensitive: <span class="bool-val">false</span>,
<a href=#142 id=142 data-nosnippet>142</a> start_bytes: StartBytesBuilder::new(),
<a href=#143 id=143 data-nosnippet>143</a> rare_bytes: RareBytesBuilder::new(),
<a href=#144 id=144 data-nosnippet>144</a> memmem: MemmemBuilder::default(),
<a href=#145 id=145 data-nosnippet>145</a> packed: pbuilder,
<a href=#146 id=146 data-nosnippet>146</a> enabled: <span class="bool-val">true</span>,
<a href=#147 id=147 data-nosnippet>147</a> }
<a href=#148 id=148 data-nosnippet>148</a> }
<a href=#149 id=149 data-nosnippet>149</a>
<a href=#150 id=150 data-nosnippet>150</a> <span class="doccomment">/// Enable ASCII case insensitivity. When set, byte strings added to this
<a href=#151 id=151 data-nosnippet>151</a> /// builder will be interpreted without respect to ASCII case.
<a href=#152 id=152 data-nosnippet>152</a> </span><span class="kw">pub</span>(<span class="kw">crate</span>) <span class="kw">fn </span>ascii_case_insensitive(<span class="kw-2">mut </span><span class="self">self</span>, yes: bool) -&gt; Builder {
<a href=#153 id=153 data-nosnippet>153</a> <span class="self">self</span>.ascii_case_insensitive = yes;
<a href=#154 id=154 data-nosnippet>154</a> <span class="self">self</span>.start_bytes = <span class="self">self</span>.start_bytes.ascii_case_insensitive(yes);
<a href=#155 id=155 data-nosnippet>155</a> <span class="self">self</span>.rare_bytes = <span class="self">self</span>.rare_bytes.ascii_case_insensitive(yes);
<a href=#156 id=156 data-nosnippet>156</a> <span class="self">self
<a href=#157 id=157 data-nosnippet>157</a> </span>}
<a href=#158 id=158 data-nosnippet>158</a>
<a href=#159 id=159 data-nosnippet>159</a> <span class="doccomment">/// Return a prefilter suitable for quickly finding potential matches.
<a href=#160 id=160 data-nosnippet>160</a> ///
<a href=#161 id=161 data-nosnippet>161</a> /// All patterns added to an Aho-Corasick automaton should be added to this
<a href=#162 id=162 data-nosnippet>162</a> /// builder before attempting to construct the prefilter.
<a href=#163 id=163 data-nosnippet>163</a> </span><span class="kw">pub</span>(<span class="kw">crate</span>) <span class="kw">fn </span>build(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; <span class="prelude-ty">Option</span>&lt;Prefilter&gt; {
<a href=#164 id=164 data-nosnippet>164</a> <span class="kw">if </span>!<span class="self">self</span>.enabled {
<a href=#165 id=165 data-nosnippet>165</a> <span class="macro">debug!</span>(<span class="string">"prefilter not enabled, skipping"</span>);
<a href=#166 id=166 data-nosnippet>166</a> <span class="kw">return </span><span class="prelude-val">None</span>;
<a href=#167 id=167 data-nosnippet>167</a> }
<a href=#168 id=168 data-nosnippet>168</a> <span class="comment">// If we only have one pattern, then deferring to memmem is always
<a href=#169 id=169 data-nosnippet>169</a> // the best choice. This is kind of a weird case, because, well, why
<a href=#170 id=170 data-nosnippet>170</a> // use Aho-Corasick if you only have one pattern? But maybe you don't
<a href=#171 id=171 data-nosnippet>171</a> // know exactly how many patterns you'll get up front, and you need to
<a href=#172 id=172 data-nosnippet>172</a> // support the option of multiple patterns. So instead of relying on
<a href=#173 id=173 data-nosnippet>173</a> // the caller to branch and use memmem explicitly, we just do it for
<a href=#174 id=174 data-nosnippet>174</a> // them.
<a href=#175 id=175 data-nosnippet>175</a> </span><span class="kw">if </span>!<span class="self">self</span>.ascii_case_insensitive {
<a href=#176 id=176 data-nosnippet>176</a> <span class="kw">if let </span><span class="prelude-val">Some</span>(pre) = <span class="self">self</span>.memmem.build() {
<a href=#177 id=177 data-nosnippet>177</a> <span class="macro">debug!</span>(<span class="string">"using memmem prefilter"</span>);
<a href=#178 id=178 data-nosnippet>178</a> <span class="kw">return </span><span class="prelude-val">Some</span>(pre);
<a href=#179 id=179 data-nosnippet>179</a> }
<a href=#180 id=180 data-nosnippet>180</a> }
<a href=#181 id=181 data-nosnippet>181</a> <span class="kw">let </span>(packed, patlen, minlen) = <span class="kw">if </span><span class="self">self</span>.ascii_case_insensitive {
<a href=#182 id=182 data-nosnippet>182</a> (<span class="prelude-val">None</span>, usize::MAX, <span class="number">0</span>)
<a href=#183 id=183 data-nosnippet>183</a> } <span class="kw">else </span>{
<a href=#184 id=184 data-nosnippet>184</a> <span class="kw">let </span>patlen = <span class="self">self</span>.packed.as_ref().map_or(usize::MAX, |p| p.len());
<a href=#185 id=185 data-nosnippet>185</a> <span class="kw">let </span>minlen = <span class="self">self</span>.packed.as_ref().map_or(<span class="number">0</span>, |p| p.minimum_len());
<a href=#186 id=186 data-nosnippet>186</a> <span class="kw">let </span>packed =
<a href=#187 id=187 data-nosnippet>187</a> <span class="self">self</span>.packed.as_ref().and_then(|b| b.build()).map(|s| {
<a href=#188 id=188 data-nosnippet>188</a> <span class="kw">let </span>memory_usage = s.memory_usage();
<a href=#189 id=189 data-nosnippet>189</a> <span class="macro">debug!</span>(
<a href=#190 id=190 data-nosnippet>190</a> <span class="string">"built packed prefilter (len: {}, \
<a href=#191 id=191 data-nosnippet>191</a> minimum pattern len: {}, memory usage: {}) \
<a href=#192 id=192 data-nosnippet>192</a> for consideration"</span>,
<a href=#193 id=193 data-nosnippet>193</a> patlen, minlen, memory_usage,
<a href=#194 id=194 data-nosnippet>194</a> );
<a href=#195 id=195 data-nosnippet>195</a> Prefilter { finder: Arc::new(Packed(s)), memory_usage }
<a href=#196 id=196 data-nosnippet>196</a> });
<a href=#197 id=197 data-nosnippet>197</a> (packed, patlen, minlen)
<a href=#198 id=198 data-nosnippet>198</a> };
<a href=#199 id=199 data-nosnippet>199</a> <span class="kw">match </span>(<span class="self">self</span>.start_bytes.build(), <span class="self">self</span>.rare_bytes.build()) {
<a href=#200 id=200 data-nosnippet>200</a> <span class="comment">// If we could build both start and rare prefilters, then there are
<a href=#201 id=201 data-nosnippet>201</a> // a few cases in which we'd want to use the start-byte prefilter
<a href=#202 id=202 data-nosnippet>202</a> // over the rare-byte prefilter, since the former has lower
<a href=#203 id=203 data-nosnippet>203</a> // overhead.
<a href=#204 id=204 data-nosnippet>204</a> </span>(prestart @ <span class="prelude-val">Some</span>(<span class="kw">_</span>), prerare @ <span class="prelude-val">Some</span>(<span class="kw">_</span>)) =&gt; {
<a href=#205 id=205 data-nosnippet>205</a> <span class="macro">debug!</span>(
<a href=#206 id=206 data-nosnippet>206</a> <span class="string">"both start (len={}, rank={}) and \
<a href=#207 id=207 data-nosnippet>207</a> rare (len={}, rank={}) byte prefilters \
<a href=#208 id=208 data-nosnippet>208</a> are available"</span>,
<a href=#209 id=209 data-nosnippet>209</a> <span class="self">self</span>.start_bytes.count,
<a href=#210 id=210 data-nosnippet>210</a> <span class="self">self</span>.start_bytes.rank_sum,
<a href=#211 id=211 data-nosnippet>211</a> <span class="self">self</span>.rare_bytes.count,
<a href=#212 id=212 data-nosnippet>212</a> <span class="self">self</span>.rare_bytes.rank_sum,
<a href=#213 id=213 data-nosnippet>213</a> );
<a href=#214 id=214 data-nosnippet>214</a> <span class="kw">if </span>patlen &lt;= <span class="number">16
<a href=#215 id=215 data-nosnippet>215</a> </span>&amp;&amp; minlen &gt;= <span class="number">2
<a href=#216 id=216 data-nosnippet>216</a> </span>&amp;&amp; <span class="self">self</span>.start_bytes.count &gt;= <span class="number">3
<a href=#217 id=217 data-nosnippet>217</a> </span>&amp;&amp; <span class="self">self</span>.rare_bytes.count &gt;= <span class="number">3
<a href=#218 id=218 data-nosnippet>218</a> </span>{
<a href=#219 id=219 data-nosnippet>219</a> <span class="macro">debug!</span>(
<a href=#220 id=220 data-nosnippet>220</a> <span class="string">"start and rare byte prefilters available, but \
<a href=#221 id=221 data-nosnippet>221</a> they're probably slower than packed so using \
<a href=#222 id=222 data-nosnippet>222</a> packed"
<a href=#223 id=223 data-nosnippet>223</a> </span>);
<a href=#224 id=224 data-nosnippet>224</a> <span class="kw">return </span>packed;
<a href=#225 id=225 data-nosnippet>225</a> }
<a href=#226 id=226 data-nosnippet>226</a> <span class="comment">// If the start-byte prefilter can scan for a smaller number
<a href=#227 id=227 data-nosnippet>227</a> // of bytes than the rare-byte prefilter, then it's probably
<a href=#228 id=228 data-nosnippet>228</a> // faster.
<a href=#229 id=229 data-nosnippet>229</a> </span><span class="kw">let </span>has_fewer_bytes =
<a href=#230 id=230 data-nosnippet>230</a> <span class="self">self</span>.start_bytes.count &lt; <span class="self">self</span>.rare_bytes.count;
<a href=#231 id=231 data-nosnippet>231</a> <span class="comment">// Otherwise, if the combined frequency rank of the detected
<a href=#232 id=232 data-nosnippet>232</a> // bytes in the start-byte prefilter is "close" to the combined
<a href=#233 id=233 data-nosnippet>233</a> // frequency rank of the rare-byte prefilter, then we pick
<a href=#234 id=234 data-nosnippet>234</a> // the start-byte prefilter even if the rare-byte prefilter
<a href=#235 id=235 data-nosnippet>235</a> // heuristically searches for rare bytes. This is because the
<a href=#236 id=236 data-nosnippet>236</a> // rare-byte prefilter has higher constant costs, so we tend to
<a href=#237 id=237 data-nosnippet>237</a> // prefer the start-byte prefilter when we can.
<a href=#238 id=238 data-nosnippet>238</a> </span><span class="kw">let </span>has_rarer_bytes =
<a href=#239 id=239 data-nosnippet>239</a> <span class="self">self</span>.start_bytes.rank_sum &lt;= <span class="self">self</span>.rare_bytes.rank_sum + <span class="number">50</span>;
<a href=#240 id=240 data-nosnippet>240</a> <span class="kw">if </span>has_fewer_bytes {
<a href=#241 id=241 data-nosnippet>241</a> <span class="macro">debug!</span>(
<a href=#242 id=242 data-nosnippet>242</a> <span class="string">"using start byte prefilter because it has fewer
<a href=#243 id=243 data-nosnippet>243</a> bytes to search for than the rare byte prefilter"</span>,
<a href=#244 id=244 data-nosnippet>244</a> );
<a href=#245 id=245 data-nosnippet>245</a> prestart
<a href=#246 id=246 data-nosnippet>246</a> } <span class="kw">else if </span>has_rarer_bytes {
<a href=#247 id=247 data-nosnippet>247</a> <span class="macro">debug!</span>(
<a href=#248 id=248 data-nosnippet>248</a> <span class="string">"using start byte prefilter because its byte \
<a href=#249 id=249 data-nosnippet>249</a> frequency rank was determined to be \
<a href=#250 id=250 data-nosnippet>250</a> \"good enough\" relative to the rare byte prefilter \
<a href=#251 id=251 data-nosnippet>251</a> byte frequency rank"</span>,
<a href=#252 id=252 data-nosnippet>252</a> );
<a href=#253 id=253 data-nosnippet>253</a> prestart
<a href=#254 id=254 data-nosnippet>254</a> } <span class="kw">else </span>{
<a href=#255 id=255 data-nosnippet>255</a> <span class="macro">debug!</span>(<span class="string">"using rare byte prefilter"</span>);
<a href=#256 id=256 data-nosnippet>256</a> prerare
<a href=#257 id=257 data-nosnippet>257</a> }
<a href=#258 id=258 data-nosnippet>258</a> }
<a href=#259 id=259 data-nosnippet>259</a> (prestart @ <span class="prelude-val">Some</span>(<span class="kw">_</span>), <span class="prelude-val">None</span>) =&gt; {
<a href=#260 id=260 data-nosnippet>260</a> <span class="kw">if </span>patlen &lt;= <span class="number">16 </span>&amp;&amp; minlen &gt;= <span class="number">2 </span>&amp;&amp; <span class="self">self</span>.start_bytes.count &gt;= <span class="number">3 </span>{
<a href=#261 id=261 data-nosnippet>261</a> <span class="macro">debug!</span>(
<a href=#262 id=262 data-nosnippet>262</a> <span class="string">"start byte prefilter available, but \
<a href=#263 id=263 data-nosnippet>263</a> it's probably slower than packed so using \
<a href=#264 id=264 data-nosnippet>264</a> packed"
<a href=#265 id=265 data-nosnippet>265</a> </span>);
<a href=#266 id=266 data-nosnippet>266</a> <span class="kw">return </span>packed;
<a href=#267 id=267 data-nosnippet>267</a> }
<a href=#268 id=268 data-nosnippet>268</a> <span class="macro">debug!</span>(
<a href=#269 id=269 data-nosnippet>269</a> <span class="string">"have start byte prefilter but not rare byte prefilter, \
<a href=#270 id=270 data-nosnippet>270</a> so using start byte prefilter"</span>,
<a href=#271 id=271 data-nosnippet>271</a> );
<a href=#272 id=272 data-nosnippet>272</a> prestart
<a href=#273 id=273 data-nosnippet>273</a> }
<a href=#274 id=274 data-nosnippet>274</a> (<span class="prelude-val">None</span>, prerare @ <span class="prelude-val">Some</span>(<span class="kw">_</span>)) =&gt; {
<a href=#275 id=275 data-nosnippet>275</a> <span class="kw">if </span>patlen &lt;= <span class="number">16 </span>&amp;&amp; minlen &gt;= <span class="number">2 </span>&amp;&amp; <span class="self">self</span>.rare_bytes.count &gt;= <span class="number">3 </span>{
<a href=#276 id=276 data-nosnippet>276</a> <span class="macro">debug!</span>(
<a href=#277 id=277 data-nosnippet>277</a> <span class="string">"rare byte prefilter available, but \
<a href=#278 id=278 data-nosnippet>278</a> it's probably slower than packed so using \
<a href=#279 id=279 data-nosnippet>279</a> packed"
<a href=#280 id=280 data-nosnippet>280</a> </span>);
<a href=#281 id=281 data-nosnippet>281</a> <span class="kw">return </span>packed;
<a href=#282 id=282 data-nosnippet>282</a> }
<a href=#283 id=283 data-nosnippet>283</a> <span class="macro">debug!</span>(
<a href=#284 id=284 data-nosnippet>284</a> <span class="string">"have rare byte prefilter but not start byte prefilter, \
<a href=#285 id=285 data-nosnippet>285</a> so using rare byte prefilter"</span>,
<a href=#286 id=286 data-nosnippet>286</a> );
<a href=#287 id=287 data-nosnippet>287</a> prerare
<a href=#288 id=288 data-nosnippet>288</a> }
<a href=#289 id=289 data-nosnippet>289</a> (<span class="prelude-val">None</span>, <span class="prelude-val">None</span>) <span class="kw">if </span><span class="self">self</span>.ascii_case_insensitive =&gt; {
<a href=#290 id=290 data-nosnippet>290</a> <span class="macro">debug!</span>(
<a href=#291 id=291 data-nosnippet>291</a> <span class="string">"no start or rare byte prefilter and ASCII case \
<a href=#292 id=292 data-nosnippet>292</a> insensitivity was enabled, so skipping prefilter"</span>,
<a href=#293 id=293 data-nosnippet>293</a> );
<a href=#294 id=294 data-nosnippet>294</a> <span class="prelude-val">None
<a href=#295 id=295 data-nosnippet>295</a> </span>}
<a href=#296 id=296 data-nosnippet>296</a> (<span class="prelude-val">None</span>, <span class="prelude-val">None</span>) =&gt; {
<a href=#297 id=297 data-nosnippet>297</a> <span class="kw">if </span>packed.is_some() {
<a href=#298 id=298 data-nosnippet>298</a> <span class="macro">debug!</span>(<span class="string">"falling back to packed prefilter"</span>);
<a href=#299 id=299 data-nosnippet>299</a> } <span class="kw">else </span>{
<a href=#300 id=300 data-nosnippet>300</a> <span class="macro">debug!</span>(<span class="string">"no prefilter available"</span>);
<a href=#301 id=301 data-nosnippet>301</a> }
<a href=#302 id=302 data-nosnippet>302</a> packed
<a href=#303 id=303 data-nosnippet>303</a> }
<a href=#304 id=304 data-nosnippet>304</a> }
<a href=#305 id=305 data-nosnippet>305</a> }
<a href=#306 id=306 data-nosnippet>306</a>
<a href=#307 id=307 data-nosnippet>307</a> <span class="doccomment">/// Add a literal string to this prefilter builder.
<a href=#308 id=308 data-nosnippet>308</a> </span><span class="kw">pub</span>(<span class="kw">crate</span>) <span class="kw">fn </span>add(<span class="kw-2">&amp;mut </span><span class="self">self</span>, bytes: <span class="kw-2">&amp;</span>[u8]) {
<a href=#309 id=309 data-nosnippet>309</a> <span class="kw">if </span>bytes.is_empty() {
<a href=#310 id=310 data-nosnippet>310</a> <span class="self">self</span>.enabled = <span class="bool-val">false</span>;
<a href=#311 id=311 data-nosnippet>311</a> }
<a href=#312 id=312 data-nosnippet>312</a> <span class="kw">if </span>!<span class="self">self</span>.enabled {
<a href=#313 id=313 data-nosnippet>313</a> <span class="kw">return</span>;
<a href=#314 id=314 data-nosnippet>314</a> }
<a href=#315 id=315 data-nosnippet>315</a> <span class="self">self</span>.count += <span class="number">1</span>;
<a href=#316 id=316 data-nosnippet>316</a> <span class="self">self</span>.start_bytes.add(bytes);
<a href=#317 id=317 data-nosnippet>317</a> <span class="self">self</span>.rare_bytes.add(bytes);
<a href=#318 id=318 data-nosnippet>318</a> <span class="self">self</span>.memmem.add(bytes);
<a href=#319 id=319 data-nosnippet>319</a> <span class="kw">if let </span><span class="prelude-val">Some</span>(<span class="kw-2">ref mut </span>pbuilder) = <span class="self">self</span>.packed {
<a href=#320 id=320 data-nosnippet>320</a> pbuilder.add(bytes);
<a href=#321 id=321 data-nosnippet>321</a> }
<a href=#322 id=322 data-nosnippet>322</a> }
<a href=#323 id=323 data-nosnippet>323</a>}
<a href=#324 id=324 data-nosnippet>324</a>
<a href=#325 id=325 data-nosnippet>325</a><span class="doccomment">/// A type that wraps a packed searcher and implements the `Prefilter`
<a href=#326 id=326 data-nosnippet>326</a>/// interface.
<a href=#327 id=327 data-nosnippet>327</a></span><span class="attr">#[derive(Clone, Debug)]
<a href=#328 id=328 data-nosnippet>328</a></span><span class="kw">struct </span>Packed(packed::Searcher);
<a href=#329 id=329 data-nosnippet>329</a>
<a href=#330 id=330 data-nosnippet>330</a><span class="kw">impl </span>PrefilterI <span class="kw">for </span>Packed {
<a href=#331 id=331 data-nosnippet>331</a> <span class="kw">fn </span>find_in(<span class="kw-2">&amp;</span><span class="self">self</span>, haystack: <span class="kw-2">&amp;</span>[u8], span: Span) -&gt; Candidate {
<a href=#332 id=332 data-nosnippet>332</a> <span class="self">self</span>.<span class="number">0
<a href=#333 id=333 data-nosnippet>333</a> </span>.find_in(haystack, span)
<a href=#334 id=334 data-nosnippet>334</a> .map_or(Candidate::None, Candidate::Match)
<a href=#335 id=335 data-nosnippet>335</a> }
<a href=#336 id=336 data-nosnippet>336</a>}
<a href=#337 id=337 data-nosnippet>337</a>
<a href=#338 id=338 data-nosnippet>338</a><span class="doccomment">/// A builder for constructing a prefilter that uses memmem.
<a href=#339 id=339 data-nosnippet>339</a></span><span class="attr">#[derive(Debug, Default)]
<a href=#340 id=340 data-nosnippet>340</a></span><span class="kw">struct </span>MemmemBuilder {
<a href=#341 id=341 data-nosnippet>341</a> <span class="doccomment">/// The number of patterns that have been added.
<a href=#342 id=342 data-nosnippet>342</a> </span>count: usize,
<a href=#343 id=343 data-nosnippet>343</a> <span class="doccomment">/// The singular pattern to search for. This is only set when count==1.
<a href=#344 id=344 data-nosnippet>344</a> </span>one: <span class="prelude-ty">Option</span>&lt;Vec&lt;u8&gt;&gt;,
<a href=#345 id=345 data-nosnippet>345</a>}
<a href=#346 id=346 data-nosnippet>346</a>
<a href=#347 id=347 data-nosnippet>347</a><span class="kw">impl </span>MemmemBuilder {
<a href=#348 id=348 data-nosnippet>348</a> <span class="kw">fn </span>build(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; <span class="prelude-ty">Option</span>&lt;Prefilter&gt; {
<a href=#349 id=349 data-nosnippet>349</a> <span class="attr">#[cfg(all(feature = <span class="string">"std"</span>, feature = <span class="string">"perf-literal"</span>))]
<a href=#350 id=350 data-nosnippet>350</a> </span><span class="kw">fn </span>imp(builder: <span class="kw-2">&amp;</span>MemmemBuilder) -&gt; <span class="prelude-ty">Option</span>&lt;Prefilter&gt; {
<a href=#351 id=351 data-nosnippet>351</a> <span class="kw">let </span>pattern = builder.one.as_ref()<span class="question-mark">?</span>;
<a href=#352 id=352 data-nosnippet>352</a> <span class="macro">assert_eq!</span>(<span class="number">1</span>, builder.count);
<a href=#353 id=353 data-nosnippet>353</a> <span class="kw">let </span>finder = Arc::new(Memmem(
<a href=#354 id=354 data-nosnippet>354</a> memchr::memmem::Finder::new(pattern).into_owned(),
<a href=#355 id=355 data-nosnippet>355</a> ));
<a href=#356 id=356 data-nosnippet>356</a> <span class="kw">let </span>memory_usage = pattern.len();
<a href=#357 id=357 data-nosnippet>357</a> <span class="prelude-val">Some</span>(Prefilter { finder, memory_usage })
<a href=#358 id=358 data-nosnippet>358</a> }
<a href=#359 id=359 data-nosnippet>359</a>
<a href=#360 id=360 data-nosnippet>360</a> <span class="attr">#[cfg(not(all(feature = <span class="string">"std"</span>, feature = <span class="string">"perf-literal"</span>)))]
<a href=#361 id=361 data-nosnippet>361</a> </span><span class="kw">fn </span>imp(<span class="kw">_</span>: <span class="kw-2">&amp;</span>MemmemBuilder) -&gt; <span class="prelude-ty">Option</span>&lt;Prefilter&gt; {
<a href=#362 id=362 data-nosnippet>362</a> <span class="prelude-val">None
<a href=#363 id=363 data-nosnippet>363</a> </span>}
<a href=#364 id=364 data-nosnippet>364</a>
<a href=#365 id=365 data-nosnippet>365</a> imp(<span class="self">self</span>)
<a href=#366 id=366 data-nosnippet>366</a> }
<a href=#367 id=367 data-nosnippet>367</a>
<a href=#368 id=368 data-nosnippet>368</a> <span class="kw">fn </span>add(<span class="kw-2">&amp;mut </span><span class="self">self</span>, bytes: <span class="kw-2">&amp;</span>[u8]) {
<a href=#369 id=369 data-nosnippet>369</a> <span class="self">self</span>.count += <span class="number">1</span>;
<a href=#370 id=370 data-nosnippet>370</a> <span class="kw">if </span><span class="self">self</span>.count == <span class="number">1 </span>{
<a href=#371 id=371 data-nosnippet>371</a> <span class="self">self</span>.one = <span class="prelude-val">Some</span>(bytes.to_vec());
<a href=#372 id=372 data-nosnippet>372</a> } <span class="kw">else </span>{
<a href=#373 id=373 data-nosnippet>373</a> <span class="self">self</span>.one = <span class="prelude-val">None</span>;
<a href=#374 id=374 data-nosnippet>374</a> }
<a href=#375 id=375 data-nosnippet>375</a> }
<a href=#376 id=376 data-nosnippet>376</a>}
<a href=#377 id=377 data-nosnippet>377</a>
<a href=#378 id=378 data-nosnippet>378</a><span class="doccomment">/// A type that wraps a SIMD accelerated single substring search from the
<a href=#379 id=379 data-nosnippet>379</a>/// `memchr` crate for use as a prefilter.
<a href=#380 id=380 data-nosnippet>380</a>///
<a href=#381 id=381 data-nosnippet>381</a>/// Currently, this prefilter is only active for Aho-Corasick searchers with
<a href=#382 id=382 data-nosnippet>382</a>/// a single pattern. In theory, this could be extended to support searchers
<a href=#383 id=383 data-nosnippet>383</a>/// that have a common prefix of more than one byte (for one byte, we would use
<a href=#384 id=384 data-nosnippet>384</a>/// memchr), but it's not clear if it's worth it or not.
<a href=#385 id=385 data-nosnippet>385</a>///
<a href=#386 id=386 data-nosnippet>386</a>/// Also, unfortunately, this currently also requires the 'std' feature to
<a href=#387 id=387 data-nosnippet>387</a>/// be enabled. That's because memchr doesn't have a no-std-but-with-alloc
<a href=#388 id=388 data-nosnippet>388</a>/// mode, and so APIs like Finder::into_owned aren't available when 'std' is
<a href=#389 id=389 data-nosnippet>389</a>/// disabled. But there should be an 'alloc' feature that brings in APIs like
<a href=#390 id=390 data-nosnippet>390</a>/// Finder::into_owned but doesn't use std-only features like runtime CPU
<a href=#391 id=391 data-nosnippet>391</a>/// feature detection.
<a href=#392 id=392 data-nosnippet>392</a></span><span class="attr">#[cfg(all(feature = <span class="string">"std"</span>, feature = <span class="string">"perf-literal"</span>))]
<a href=#393 id=393 data-nosnippet>393</a>#[derive(Clone, Debug)]
<a href=#394 id=394 data-nosnippet>394</a></span><span class="kw">struct </span>Memmem(memchr::memmem::Finder&lt;<span class="lifetime">'static</span>&gt;);
<a href=#395 id=395 data-nosnippet>395</a>
<a href=#396 id=396 data-nosnippet>396</a><span class="attr">#[cfg(all(feature = <span class="string">"std"</span>, feature = <span class="string">"perf-literal"</span>))]
<a href=#397 id=397 data-nosnippet>397</a></span><span class="kw">impl </span>PrefilterI <span class="kw">for </span>Memmem {
<a href=#398 id=398 data-nosnippet>398</a> <span class="kw">fn </span>find_in(<span class="kw-2">&amp;</span><span class="self">self</span>, haystack: <span class="kw-2">&amp;</span>[u8], span: Span) -&gt; Candidate {
<a href=#399 id=399 data-nosnippet>399</a> <span class="kw">use </span><span class="kw">crate</span>::util::primitives::PatternID;
<a href=#400 id=400 data-nosnippet>400</a>
<a href=#401 id=401 data-nosnippet>401</a> <span class="self">self</span>.<span class="number">0</span>.find(<span class="kw-2">&amp;</span>haystack[span]).map_or(Candidate::None, |i| {
<a href=#402 id=402 data-nosnippet>402</a> <span class="kw">let </span>start = span.start + i;
<a href=#403 id=403 data-nosnippet>403</a> <span class="kw">let </span>end = start + <span class="self">self</span>.<span class="number">0</span>.needle().len();
<a href=#404 id=404 data-nosnippet>404</a> <span class="comment">// N.B. We can declare a match and use a fixed pattern ID here
<a href=#405 id=405 data-nosnippet>405</a> // because a Memmem prefilter is only ever created for searchers
<a href=#406 id=406 data-nosnippet>406</a> // with exactly one pattern. Thus, every match is always a match
<a href=#407 id=407 data-nosnippet>407</a> // and it is always for the first and only pattern.
<a href=#408 id=408 data-nosnippet>408</a> </span>Candidate::Match(Match::new(PatternID::ZERO, start..end))
<a href=#409 id=409 data-nosnippet>409</a> })
<a href=#410 id=410 data-nosnippet>410</a> }
<a href=#411 id=411 data-nosnippet>411</a>}
<a href=#412 id=412 data-nosnippet>412</a>
<a href=#413 id=413 data-nosnippet>413</a><span class="doccomment">/// A builder for constructing a rare byte prefilter.
<a href=#414 id=414 data-nosnippet>414</a>///
<a href=#415 id=415 data-nosnippet>415</a>/// A rare byte prefilter attempts to pick out a small set of rare bytes that
<a href=#416 id=416 data-nosnippet>416</a>/// occurr in the patterns, and then quickly scan to matches of those rare
<a href=#417 id=417 data-nosnippet>417</a>/// bytes.
<a href=#418 id=418 data-nosnippet>418</a></span><span class="attr">#[derive(Clone, Debug)]
<a href=#419 id=419 data-nosnippet>419</a></span><span class="kw">struct </span>RareBytesBuilder {
<a href=#420 id=420 data-nosnippet>420</a> <span class="doccomment">/// Whether this prefilter should account for ASCII case insensitivity or
<a href=#421 id=421 data-nosnippet>421</a> /// not.
<a href=#422 id=422 data-nosnippet>422</a> </span>ascii_case_insensitive: bool,
<a href=#423 id=423 data-nosnippet>423</a> <span class="doccomment">/// A set of rare bytes, indexed by byte value.
<a href=#424 id=424 data-nosnippet>424</a> </span>rare_set: ByteSet,
<a href=#425 id=425 data-nosnippet>425</a> <span class="doccomment">/// A set of byte offsets associated with bytes in a pattern. An entry
<a href=#426 id=426 data-nosnippet>426</a> /// corresponds to a particular bytes (its index) and is only non-zero if
<a href=#427 id=427 data-nosnippet>427</a> /// the byte occurred at an offset greater than 0 in at least one pattern.
<a href=#428 id=428 data-nosnippet>428</a> ///
<a href=#429 id=429 data-nosnippet>429</a> /// If a byte's offset is not representable in 8 bits, then the rare bytes
<a href=#430 id=430 data-nosnippet>430</a> /// prefilter becomes inert.
<a href=#431 id=431 data-nosnippet>431</a> </span>byte_offsets: RareByteOffsets,
<a href=#432 id=432 data-nosnippet>432</a> <span class="doccomment">/// Whether this is available as a prefilter or not. This can be set to
<a href=#433 id=433 data-nosnippet>433</a> /// false during construction if a condition is seen that invalidates the
<a href=#434 id=434 data-nosnippet>434</a> /// use of the rare-byte prefilter.
<a href=#435 id=435 data-nosnippet>435</a> </span>available: bool,
<a href=#436 id=436 data-nosnippet>436</a> <span class="doccomment">/// The number of bytes set to an active value in `byte_offsets`.
<a href=#437 id=437 data-nosnippet>437</a> </span>count: usize,
<a href=#438 id=438 data-nosnippet>438</a> <span class="doccomment">/// The sum of frequency ranks for the rare bytes detected. This is
<a href=#439 id=439 data-nosnippet>439</a> /// intended to give a heuristic notion of how rare the bytes are.
<a href=#440 id=440 data-nosnippet>440</a> </span>rank_sum: u16,
<a href=#441 id=441 data-nosnippet>441</a>}
<a href=#442 id=442 data-nosnippet>442</a>
<a href=#443 id=443 data-nosnippet>443</a><span class="doccomment">/// A set of byte offsets, keyed by byte.
<a href=#444 id=444 data-nosnippet>444</a></span><span class="attr">#[derive(Clone, Copy)]
<a href=#445 id=445 data-nosnippet>445</a></span><span class="kw">struct </span>RareByteOffsets {
<a href=#446 id=446 data-nosnippet>446</a> <span class="doccomment">/// Each entry corresponds to the maximum offset of the corresponding
<a href=#447 id=447 data-nosnippet>447</a> /// byte across all patterns seen.
<a href=#448 id=448 data-nosnippet>448</a> </span>set: [RareByteOffset; <span class="number">256</span>],
<a href=#449 id=449 data-nosnippet>449</a>}
<a href=#450 id=450 data-nosnippet>450</a>
<a href=#451 id=451 data-nosnippet>451</a><span class="kw">impl </span>RareByteOffsets {
<a href=#452 id=452 data-nosnippet>452</a> <span class="doccomment">/// Create a new empty set of rare byte offsets.
<a href=#453 id=453 data-nosnippet>453</a> </span><span class="kw">pub</span>(<span class="kw">crate</span>) <span class="kw">fn </span>empty() -&gt; RareByteOffsets {
<a href=#454 id=454 data-nosnippet>454</a> RareByteOffsets { set: [RareByteOffset::default(); <span class="number">256</span>] }
<a href=#455 id=455 data-nosnippet>455</a> }
<a href=#456 id=456 data-nosnippet>456</a>
<a href=#457 id=457 data-nosnippet>457</a> <span class="doccomment">/// Add the given offset for the given byte to this set. If the offset is
<a href=#458 id=458 data-nosnippet>458</a> /// greater than the existing offset, then it overwrites the previous
<a href=#459 id=459 data-nosnippet>459</a> /// value and returns false. If there is no previous value set, then this
<a href=#460 id=460 data-nosnippet>460</a> /// sets it and returns true.
<a href=#461 id=461 data-nosnippet>461</a> </span><span class="kw">pub</span>(<span class="kw">crate</span>) <span class="kw">fn </span>set(<span class="kw-2">&amp;mut </span><span class="self">self</span>, byte: u8, off: RareByteOffset) {
<a href=#462 id=462 data-nosnippet>462</a> <span class="self">self</span>.set[byte <span class="kw">as </span>usize].max =
<a href=#463 id=463 data-nosnippet>463</a> cmp::max(<span class="self">self</span>.set[byte <span class="kw">as </span>usize].max, off.max);
<a href=#464 id=464 data-nosnippet>464</a> }
<a href=#465 id=465 data-nosnippet>465</a>}
<a href=#466 id=466 data-nosnippet>466</a>
<a href=#467 id=467 data-nosnippet>467</a><span class="kw">impl </span>core::fmt::Debug <span class="kw">for </span>RareByteOffsets {
<a href=#468 id=468 data-nosnippet>468</a> <span class="kw">fn </span>fmt(<span class="kw-2">&amp;</span><span class="self">self</span>, f: <span class="kw-2">&amp;mut </span>core::fmt::Formatter&lt;<span class="lifetime">'_</span>&gt;) -&gt; core::fmt::Result {
<a href=#469 id=469 data-nosnippet>469</a> <span class="kw">let </span><span class="kw-2">mut </span>offsets = <span class="macro">vec!</span>[];
<a href=#470 id=470 data-nosnippet>470</a> <span class="kw">for </span>off <span class="kw">in </span><span class="self">self</span>.set.iter() {
<a href=#471 id=471 data-nosnippet>471</a> <span class="kw">if </span>off.max &gt; <span class="number">0 </span>{
<a href=#472 id=472 data-nosnippet>472</a> offsets.push(off);
<a href=#473 id=473 data-nosnippet>473</a> }
<a href=#474 id=474 data-nosnippet>474</a> }
<a href=#475 id=475 data-nosnippet>475</a> f.debug_struct(<span class="string">"RareByteOffsets"</span>).field(<span class="string">"set"</span>, <span class="kw-2">&amp;</span>offsets).finish()
<a href=#476 id=476 data-nosnippet>476</a> }
<a href=#477 id=477 data-nosnippet>477</a>}
<a href=#478 id=478 data-nosnippet>478</a>
<a href=#479 id=479 data-nosnippet>479</a><span class="doccomment">/// Offsets associated with an occurrence of a "rare" byte in any of the
<a href=#480 id=480 data-nosnippet>480</a>/// patterns used to construct a single Aho-Corasick automaton.
<a href=#481 id=481 data-nosnippet>481</a></span><span class="attr">#[derive(Clone, Copy, Debug)]
<a href=#482 id=482 data-nosnippet>482</a></span><span class="kw">struct </span>RareByteOffset {
<a href=#483 id=483 data-nosnippet>483</a> <span class="doccomment">/// The maximum offset at which a particular byte occurs from the start
<a href=#484 id=484 data-nosnippet>484</a> /// of any pattern. This is used as a shift amount. That is, when an
<a href=#485 id=485 data-nosnippet>485</a> /// occurrence of this byte is found, the candidate position reported by
<a href=#486 id=486 data-nosnippet>486</a> /// the prefilter is `position_of_byte - max`, such that the automaton
<a href=#487 id=487 data-nosnippet>487</a> /// will begin its search at a position that is guaranteed to observe a
<a href=#488 id=488 data-nosnippet>488</a> /// match.
<a href=#489 id=489 data-nosnippet>489</a> ///
<a href=#490 id=490 data-nosnippet>490</a> /// To avoid accidentally quadratic behavior, a prefilter is considered
<a href=#491 id=491 data-nosnippet>491</a> /// ineffective when it is asked to start scanning from a position that it
<a href=#492 id=492 data-nosnippet>492</a> /// has already scanned past.
<a href=#493 id=493 data-nosnippet>493</a> ///
<a href=#494 id=494 data-nosnippet>494</a> /// Using a `u8` here means that if we ever see a pattern that's longer
<a href=#495 id=495 data-nosnippet>495</a> /// than 255 bytes, then the entire rare byte prefilter is disabled.
<a href=#496 id=496 data-nosnippet>496</a> </span>max: u8,
<a href=#497 id=497 data-nosnippet>497</a>}
<a href=#498 id=498 data-nosnippet>498</a>
<a href=#499 id=499 data-nosnippet>499</a><span class="kw">impl </span>Default <span class="kw">for </span>RareByteOffset {
<a href=#500 id=500 data-nosnippet>500</a> <span class="kw">fn </span>default() -&gt; RareByteOffset {
<a href=#501 id=501 data-nosnippet>501</a> RareByteOffset { max: <span class="number">0 </span>}
<a href=#502 id=502 data-nosnippet>502</a> }
<a href=#503 id=503 data-nosnippet>503</a>}
<a href=#504 id=504 data-nosnippet>504</a>
<a href=#505 id=505 data-nosnippet>505</a><span class="kw">impl </span>RareByteOffset {
<a href=#506 id=506 data-nosnippet>506</a> <span class="doccomment">/// Create a new rare byte offset. If the given offset is too big, then
<a href=#507 id=507 data-nosnippet>507</a> /// None is returned. In that case, callers should render the rare bytes
<a href=#508 id=508 data-nosnippet>508</a> /// prefilter inert.
<a href=#509 id=509 data-nosnippet>509</a> </span><span class="kw">fn </span>new(max: usize) -&gt; <span class="prelude-ty">Option</span>&lt;RareByteOffset&gt; {
<a href=#510 id=510 data-nosnippet>510</a> <span class="kw">if </span>max &gt; u8::MAX <span class="kw">as </span>usize {
<a href=#511 id=511 data-nosnippet>511</a> <span class="prelude-val">None
<a href=#512 id=512 data-nosnippet>512</a> </span>} <span class="kw">else </span>{
<a href=#513 id=513 data-nosnippet>513</a> <span class="prelude-val">Some</span>(RareByteOffset { max: max <span class="kw">as </span>u8 })
<a href=#514 id=514 data-nosnippet>514</a> }
<a href=#515 id=515 data-nosnippet>515</a> }
<a href=#516 id=516 data-nosnippet>516</a>}
<a href=#517 id=517 data-nosnippet>517</a>
<a href=#518 id=518 data-nosnippet>518</a><span class="kw">impl </span>RareBytesBuilder {
<a href=#519 id=519 data-nosnippet>519</a> <span class="doccomment">/// Create a new builder for constructing a rare byte prefilter.
<a href=#520 id=520 data-nosnippet>520</a> </span><span class="kw">fn </span>new() -&gt; RareBytesBuilder {
<a href=#521 id=521 data-nosnippet>521</a> RareBytesBuilder {
<a href=#522 id=522 data-nosnippet>522</a> ascii_case_insensitive: <span class="bool-val">false</span>,
<a href=#523 id=523 data-nosnippet>523</a> rare_set: ByteSet::empty(),
<a href=#524 id=524 data-nosnippet>524</a> byte_offsets: RareByteOffsets::empty(),
<a href=#525 id=525 data-nosnippet>525</a> available: <span class="bool-val">true</span>,
<a href=#526 id=526 data-nosnippet>526</a> count: <span class="number">0</span>,
<a href=#527 id=527 data-nosnippet>527</a> rank_sum: <span class="number">0</span>,
<a href=#528 id=528 data-nosnippet>528</a> }
<a href=#529 id=529 data-nosnippet>529</a> }
<a href=#530 id=530 data-nosnippet>530</a>
<a href=#531 id=531 data-nosnippet>531</a> <span class="doccomment">/// Enable ASCII case insensitivity. When set, byte strings added to this
<a href=#532 id=532 data-nosnippet>532</a> /// builder will be interpreted without respect to ASCII case.
<a href=#533 id=533 data-nosnippet>533</a> </span><span class="kw">fn </span>ascii_case_insensitive(<span class="kw-2">mut </span><span class="self">self</span>, yes: bool) -&gt; RareBytesBuilder {
<a href=#534 id=534 data-nosnippet>534</a> <span class="self">self</span>.ascii_case_insensitive = yes;
<a href=#535 id=535 data-nosnippet>535</a> <span class="self">self
<a href=#536 id=536 data-nosnippet>536</a> </span>}
<a href=#537 id=537 data-nosnippet>537</a>
<a href=#538 id=538 data-nosnippet>538</a> <span class="doccomment">/// Build the rare bytes prefilter.
<a href=#539 id=539 data-nosnippet>539</a> ///
<a href=#540 id=540 data-nosnippet>540</a> /// If there are more than 3 distinct rare bytes found, or if heuristics
<a href=#541 id=541 data-nosnippet>541</a> /// otherwise determine that this prefilter should not be used, then `None`
<a href=#542 id=542 data-nosnippet>542</a> /// is returned.
<a href=#543 id=543 data-nosnippet>543</a> </span><span class="kw">fn </span>build(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; <span class="prelude-ty">Option</span>&lt;Prefilter&gt; {
<a href=#544 id=544 data-nosnippet>544</a> <span class="attr">#[cfg(feature = <span class="string">"perf-literal"</span>)]
<a href=#545 id=545 data-nosnippet>545</a> </span><span class="kw">fn </span>imp(builder: <span class="kw-2">&amp;</span>RareBytesBuilder) -&gt; <span class="prelude-ty">Option</span>&lt;Prefilter&gt; {
<a href=#546 id=546 data-nosnippet>546</a> <span class="kw">if </span>!builder.available || builder.count &gt; <span class="number">3 </span>{
<a href=#547 id=547 data-nosnippet>547</a> <span class="kw">return </span><span class="prelude-val">None</span>;
<a href=#548 id=548 data-nosnippet>548</a> }
<a href=#549 id=549 data-nosnippet>549</a> <span class="kw">let </span>(<span class="kw-2">mut </span>bytes, <span class="kw-2">mut </span>len) = ([<span class="number">0</span>; <span class="number">3</span>], <span class="number">0</span>);
<a href=#550 id=550 data-nosnippet>550</a> <span class="kw">for </span>b <span class="kw">in </span><span class="number">0</span>..=<span class="number">255 </span>{
<a href=#551 id=551 data-nosnippet>551</a> <span class="kw">if </span>builder.rare_set.contains(b) {
<a href=#552 id=552 data-nosnippet>552</a> bytes[len] = b;
<a href=#553 id=553 data-nosnippet>553</a> len += <span class="number">1</span>;
<a href=#554 id=554 data-nosnippet>554</a> }
<a href=#555 id=555 data-nosnippet>555</a> }
<a href=#556 id=556 data-nosnippet>556</a> <span class="kw">let </span>finder: Arc&lt;<span class="kw">dyn </span>PrefilterI&gt; = <span class="kw">match </span>len {
<a href=#557 id=557 data-nosnippet>557</a> <span class="number">0 </span>=&gt; <span class="kw">return </span><span class="prelude-val">None</span>,
<a href=#558 id=558 data-nosnippet>558</a> <span class="number">1 </span>=&gt; Arc::new(RareBytesOne {
<a href=#559 id=559 data-nosnippet>559</a> byte1: bytes[<span class="number">0</span>],
<a href=#560 id=560 data-nosnippet>560</a> offset: builder.byte_offsets.set[bytes[<span class="number">0</span>] <span class="kw">as </span>usize],
<a href=#561 id=561 data-nosnippet>561</a> }),
<a href=#562 id=562 data-nosnippet>562</a> <span class="number">2 </span>=&gt; Arc::new(RareBytesTwo {
<a href=#563 id=563 data-nosnippet>563</a> offsets: builder.byte_offsets,
<a href=#564 id=564 data-nosnippet>564</a> byte1: bytes[<span class="number">0</span>],
<a href=#565 id=565 data-nosnippet>565</a> byte2: bytes[<span class="number">1</span>],
<a href=#566 id=566 data-nosnippet>566</a> }),
<a href=#567 id=567 data-nosnippet>567</a> <span class="number">3 </span>=&gt; Arc::new(RareBytesThree {
<a href=#568 id=568 data-nosnippet>568</a> offsets: builder.byte_offsets,
<a href=#569 id=569 data-nosnippet>569</a> byte1: bytes[<span class="number">0</span>],
<a href=#570 id=570 data-nosnippet>570</a> byte2: bytes[<span class="number">1</span>],
<a href=#571 id=571 data-nosnippet>571</a> byte3: bytes[<span class="number">2</span>],
<a href=#572 id=572 data-nosnippet>572</a> }),
<a href=#573 id=573 data-nosnippet>573</a> <span class="kw">_ </span>=&gt; <span class="macro">unreachable!</span>(),
<a href=#574 id=574 data-nosnippet>574</a> };
<a href=#575 id=575 data-nosnippet>575</a> <span class="prelude-val">Some</span>(Prefilter { finder, memory_usage: <span class="number">0 </span>})
<a href=#576 id=576 data-nosnippet>576</a> }
<a href=#577 id=577 data-nosnippet>577</a>
<a href=#578 id=578 data-nosnippet>578</a> <span class="attr">#[cfg(not(feature = <span class="string">"perf-literal"</span>))]
<a href=#579 id=579 data-nosnippet>579</a> </span><span class="kw">fn </span>imp(<span class="kw">_</span>: <span class="kw-2">&amp;</span>RareBytesBuilder) -&gt; <span class="prelude-ty">Option</span>&lt;Prefilter&gt; {
<a href=#580 id=580 data-nosnippet>580</a> <span class="prelude-val">None
<a href=#581 id=581 data-nosnippet>581</a> </span>}
<a href=#582 id=582 data-nosnippet>582</a>
<a href=#583 id=583 data-nosnippet>583</a> imp(<span class="self">self</span>)
<a href=#584 id=584 data-nosnippet>584</a> }
<a href=#585 id=585 data-nosnippet>585</a>
<a href=#586 id=586 data-nosnippet>586</a> <span class="doccomment">/// Add a byte string to this builder.
<a href=#587 id=587 data-nosnippet>587</a> ///
<a href=#588 id=588 data-nosnippet>588</a> /// All patterns added to an Aho-Corasick automaton should be added to this
<a href=#589 id=589 data-nosnippet>589</a> /// builder before attempting to construct the prefilter.
<a href=#590 id=590 data-nosnippet>590</a> </span><span class="kw">fn </span>add(<span class="kw-2">&amp;mut </span><span class="self">self</span>, bytes: <span class="kw-2">&amp;</span>[u8]) {
<a href=#591 id=591 data-nosnippet>591</a> <span class="comment">// If we've already given up, then do nothing.
<a href=#592 id=592 data-nosnippet>592</a> </span><span class="kw">if </span>!<span class="self">self</span>.available {
<a href=#593 id=593 data-nosnippet>593</a> <span class="kw">return</span>;
<a href=#594 id=594 data-nosnippet>594</a> }
<a href=#595 id=595 data-nosnippet>595</a> <span class="comment">// If we've already blown our budget, then don't waste time looking
<a href=#596 id=596 data-nosnippet>596</a> // for more rare bytes.
<a href=#597 id=597 data-nosnippet>597</a> </span><span class="kw">if </span><span class="self">self</span>.count &gt; <span class="number">3 </span>{
<a href=#598 id=598 data-nosnippet>598</a> <span class="self">self</span>.available = <span class="bool-val">false</span>;
<a href=#599 id=599 data-nosnippet>599</a> <span class="kw">return</span>;
<a href=#600 id=600 data-nosnippet>600</a> }
<a href=#601 id=601 data-nosnippet>601</a> <span class="comment">// If the pattern is too long, then our offset table is bunk, so
<a href=#602 id=602 data-nosnippet>602</a> // give up.
<a href=#603 id=603 data-nosnippet>603</a> </span><span class="kw">if </span>bytes.len() &gt;= <span class="number">256 </span>{
<a href=#604 id=604 data-nosnippet>604</a> <span class="self">self</span>.available = <span class="bool-val">false</span>;
<a href=#605 id=605 data-nosnippet>605</a> <span class="kw">return</span>;
<a href=#606 id=606 data-nosnippet>606</a> }
<a href=#607 id=607 data-nosnippet>607</a> <span class="kw">let </span><span class="kw-2">mut </span>rarest = <span class="kw">match </span>bytes.first() {
<a href=#608 id=608 data-nosnippet>608</a> <span class="prelude-val">None </span>=&gt; <span class="kw">return</span>,
<a href=#609 id=609 data-nosnippet>609</a> <span class="prelude-val">Some</span>(<span class="kw-2">&amp;</span>b) =&gt; (b, freq_rank(b)),
<a href=#610 id=610 data-nosnippet>610</a> };
<a href=#611 id=611 data-nosnippet>611</a> <span class="comment">// The idea here is to look for the rarest byte in each pattern, and
<a href=#612 id=612 data-nosnippet>612</a> // add that to our set. As a special exception, if we see a byte that
<a href=#613 id=613 data-nosnippet>613</a> // we've already added, then we immediately stop and choose that byte,
<a href=#614 id=614 data-nosnippet>614</a> // even if there's another rare byte in the pattern. This helps us
<a href=#615 id=615 data-nosnippet>615</a> // apply the rare byte optimization in more cases by attempting to pick
<a href=#616 id=616 data-nosnippet>616</a> // bytes that are in common between patterns. So for example, if we
<a href=#617 id=617 data-nosnippet>617</a> // were searching for `Sherlock` and `lockjaw`, then this would pick
<a href=#618 id=618 data-nosnippet>618</a> // `k` for both patterns, resulting in the use of `memchr` instead of
<a href=#619 id=619 data-nosnippet>619</a> // `memchr2` for `k` and `j`.
<a href=#620 id=620 data-nosnippet>620</a> </span><span class="kw">let </span><span class="kw-2">mut </span>found = <span class="bool-val">false</span>;
<a href=#621 id=621 data-nosnippet>621</a> <span class="kw">for </span>(pos, <span class="kw-2">&amp;</span>b) <span class="kw">in </span>bytes.iter().enumerate() {
<a href=#622 id=622 data-nosnippet>622</a> <span class="self">self</span>.set_offset(pos, b);
<a href=#623 id=623 data-nosnippet>623</a> <span class="kw">if </span>found {
<a href=#624 id=624 data-nosnippet>624</a> <span class="kw">continue</span>;
<a href=#625 id=625 data-nosnippet>625</a> }
<a href=#626 id=626 data-nosnippet>626</a> <span class="kw">if </span><span class="self">self</span>.rare_set.contains(b) {
<a href=#627 id=627 data-nosnippet>627</a> found = <span class="bool-val">true</span>;
<a href=#628 id=628 data-nosnippet>628</a> <span class="kw">continue</span>;
<a href=#629 id=629 data-nosnippet>629</a> }
<a href=#630 id=630 data-nosnippet>630</a> <span class="kw">let </span>rank = freq_rank(b);
<a href=#631 id=631 data-nosnippet>631</a> <span class="kw">if </span>rank &lt; rarest.<span class="number">1 </span>{
<a href=#632 id=632 data-nosnippet>632</a> rarest = (b, rank);
<a href=#633 id=633 data-nosnippet>633</a> }
<a href=#634 id=634 data-nosnippet>634</a> }
<a href=#635 id=635 data-nosnippet>635</a> <span class="kw">if </span>!found {
<a href=#636 id=636 data-nosnippet>636</a> <span class="self">self</span>.add_rare_byte(rarest.<span class="number">0</span>);
<a href=#637 id=637 data-nosnippet>637</a> }
<a href=#638 id=638 data-nosnippet>638</a> }
<a href=#639 id=639 data-nosnippet>639</a>
<a href=#640 id=640 data-nosnippet>640</a> <span class="kw">fn </span>set_offset(<span class="kw-2">&amp;mut </span><span class="self">self</span>, pos: usize, byte: u8) {
<a href=#641 id=641 data-nosnippet>641</a> <span class="comment">// This unwrap is OK because pos is never bigger than our max.
<a href=#642 id=642 data-nosnippet>642</a> </span><span class="kw">let </span>offset = RareByteOffset::new(pos).unwrap();
<a href=#643 id=643 data-nosnippet>643</a> <span class="self">self</span>.byte_offsets.set(byte, offset);
<a href=#644 id=644 data-nosnippet>644</a> <span class="kw">if </span><span class="self">self</span>.ascii_case_insensitive {
<a href=#645 id=645 data-nosnippet>645</a> <span class="self">self</span>.byte_offsets.set(opposite_ascii_case(byte), offset);
<a href=#646 id=646 data-nosnippet>646</a> }
<a href=#647 id=647 data-nosnippet>647</a> }
<a href=#648 id=648 data-nosnippet>648</a>
<a href=#649 id=649 data-nosnippet>649</a> <span class="kw">fn </span>add_rare_byte(<span class="kw-2">&amp;mut </span><span class="self">self</span>, byte: u8) {
<a href=#650 id=650 data-nosnippet>650</a> <span class="self">self</span>.add_one_rare_byte(byte);
<a href=#651 id=651 data-nosnippet>651</a> <span class="kw">if </span><span class="self">self</span>.ascii_case_insensitive {
<a href=#652 id=652 data-nosnippet>652</a> <span class="self">self</span>.add_one_rare_byte(opposite_ascii_case(byte));
<a href=#653 id=653 data-nosnippet>653</a> }
<a href=#654 id=654 data-nosnippet>654</a> }
<a href=#655 id=655 data-nosnippet>655</a>
<a href=#656 id=656 data-nosnippet>656</a> <span class="kw">fn </span>add_one_rare_byte(<span class="kw-2">&amp;mut </span><span class="self">self</span>, byte: u8) {
<a href=#657 id=657 data-nosnippet>657</a> <span class="kw">if </span>!<span class="self">self</span>.rare_set.contains(byte) {
<a href=#658 id=658 data-nosnippet>658</a> <span class="self">self</span>.rare_set.add(byte);
<a href=#659 id=659 data-nosnippet>659</a> <span class="self">self</span>.count += <span class="number">1</span>;
<a href=#660 id=660 data-nosnippet>660</a> <span class="self">self</span>.rank_sum += freq_rank(byte) <span class="kw">as </span>u16;
<a href=#661 id=661 data-nosnippet>661</a> }
<a href=#662 id=662 data-nosnippet>662</a> }
<a href=#663 id=663 data-nosnippet>663</a>}
<a href=#664 id=664 data-nosnippet>664</a>
<a href=#665 id=665 data-nosnippet>665</a><span class="doccomment">/// A prefilter for scanning for a single "rare" byte.
<a href=#666 id=666 data-nosnippet>666</a></span><span class="attr">#[cfg(feature = <span class="string">"perf-literal"</span>)]
<a href=#667 id=667 data-nosnippet>667</a>#[derive(Clone, Debug)]
<a href=#668 id=668 data-nosnippet>668</a></span><span class="kw">struct </span>RareBytesOne {
<a href=#669 id=669 data-nosnippet>669</a> byte1: u8,
<a href=#670 id=670 data-nosnippet>670</a> offset: RareByteOffset,
<a href=#671 id=671 data-nosnippet>671</a>}
<a href=#672 id=672 data-nosnippet>672</a>
<a href=#673 id=673 data-nosnippet>673</a><span class="attr">#[cfg(feature = <span class="string">"perf-literal"</span>)]
<a href=#674 id=674 data-nosnippet>674</a></span><span class="kw">impl </span>PrefilterI <span class="kw">for </span>RareBytesOne {
<a href=#675 id=675 data-nosnippet>675</a> <span class="kw">fn </span>find_in(<span class="kw-2">&amp;</span><span class="self">self</span>, haystack: <span class="kw-2">&amp;</span>[u8], span: Span) -&gt; Candidate {
<a href=#676 id=676 data-nosnippet>676</a> memchr::memchr(<span class="self">self</span>.byte1, <span class="kw-2">&amp;</span>haystack[span])
<a href=#677 id=677 data-nosnippet>677</a> .map(|i| {
<a href=#678 id=678 data-nosnippet>678</a> <span class="kw">let </span>pos = span.start + i;
<a href=#679 id=679 data-nosnippet>679</a> cmp::max(
<a href=#680 id=680 data-nosnippet>680</a> span.start,
<a href=#681 id=681 data-nosnippet>681</a> pos.saturating_sub(usize::from(<span class="self">self</span>.offset.max)),
<a href=#682 id=682 data-nosnippet>682</a> )
<a href=#683 id=683 data-nosnippet>683</a> })
<a href=#684 id=684 data-nosnippet>684</a> .map_or(Candidate::None, Candidate::PossibleStartOfMatch)
<a href=#685 id=685 data-nosnippet>685</a> }
<a href=#686 id=686 data-nosnippet>686</a>}
<a href=#687 id=687 data-nosnippet>687</a>
<a href=#688 id=688 data-nosnippet>688</a><span class="doccomment">/// A prefilter for scanning for two "rare" bytes.
<a href=#689 id=689 data-nosnippet>689</a></span><span class="attr">#[cfg(feature = <span class="string">"perf-literal"</span>)]
<a href=#690 id=690 data-nosnippet>690</a>#[derive(Clone, Debug)]
<a href=#691 id=691 data-nosnippet>691</a></span><span class="kw">struct </span>RareBytesTwo {
<a href=#692 id=692 data-nosnippet>692</a> offsets: RareByteOffsets,
<a href=#693 id=693 data-nosnippet>693</a> byte1: u8,
<a href=#694 id=694 data-nosnippet>694</a> byte2: u8,
<a href=#695 id=695 data-nosnippet>695</a>}
<a href=#696 id=696 data-nosnippet>696</a>
<a href=#697 id=697 data-nosnippet>697</a><span class="attr">#[cfg(feature = <span class="string">"perf-literal"</span>)]
<a href=#698 id=698 data-nosnippet>698</a></span><span class="kw">impl </span>PrefilterI <span class="kw">for </span>RareBytesTwo {
<a href=#699 id=699 data-nosnippet>699</a> <span class="kw">fn </span>find_in(<span class="kw-2">&amp;</span><span class="self">self</span>, haystack: <span class="kw-2">&amp;</span>[u8], span: Span) -&gt; Candidate {
<a href=#700 id=700 data-nosnippet>700</a> memchr::memchr2(<span class="self">self</span>.byte1, <span class="self">self</span>.byte2, <span class="kw-2">&amp;</span>haystack[span])
<a href=#701 id=701 data-nosnippet>701</a> .map(|i| {
<a href=#702 id=702 data-nosnippet>702</a> <span class="kw">let </span>pos = span.start + i;
<a href=#703 id=703 data-nosnippet>703</a> <span class="kw">let </span>offset = <span class="self">self</span>.offsets.set[usize::from(haystack[pos])].max;
<a href=#704 id=704 data-nosnippet>704</a> cmp::max(span.start, pos.saturating_sub(usize::from(offset)))
<a href=#705 id=705 data-nosnippet>705</a> })
<a href=#706 id=706 data-nosnippet>706</a> .map_or(Candidate::None, Candidate::PossibleStartOfMatch)
<a href=#707 id=707 data-nosnippet>707</a> }
<a href=#708 id=708 data-nosnippet>708</a>}
<a href=#709 id=709 data-nosnippet>709</a>
<a href=#710 id=710 data-nosnippet>710</a><span class="doccomment">/// A prefilter for scanning for three "rare" bytes.
<a href=#711 id=711 data-nosnippet>711</a></span><span class="attr">#[cfg(feature = <span class="string">"perf-literal"</span>)]
<a href=#712 id=712 data-nosnippet>712</a>#[derive(Clone, Debug)]
<a href=#713 id=713 data-nosnippet>713</a></span><span class="kw">struct </span>RareBytesThree {
<a href=#714 id=714 data-nosnippet>714</a> offsets: RareByteOffsets,
<a href=#715 id=715 data-nosnippet>715</a> byte1: u8,
<a href=#716 id=716 data-nosnippet>716</a> byte2: u8,
<a href=#717 id=717 data-nosnippet>717</a> byte3: u8,
<a href=#718 id=718 data-nosnippet>718</a>}
<a href=#719 id=719 data-nosnippet>719</a>
<a href=#720 id=720 data-nosnippet>720</a><span class="attr">#[cfg(feature = <span class="string">"perf-literal"</span>)]
<a href=#721 id=721 data-nosnippet>721</a></span><span class="kw">impl </span>PrefilterI <span class="kw">for </span>RareBytesThree {
<a href=#722 id=722 data-nosnippet>722</a> <span class="kw">fn </span>find_in(<span class="kw-2">&amp;</span><span class="self">self</span>, haystack: <span class="kw-2">&amp;</span>[u8], span: Span) -&gt; Candidate {
<a href=#723 id=723 data-nosnippet>723</a> memchr::memchr3(<span class="self">self</span>.byte1, <span class="self">self</span>.byte2, <span class="self">self</span>.byte3, <span class="kw-2">&amp;</span>haystack[span])
<a href=#724 id=724 data-nosnippet>724</a> .map(|i| {
<a href=#725 id=725 data-nosnippet>725</a> <span class="kw">let </span>pos = span.start + i;
<a href=#726 id=726 data-nosnippet>726</a> <span class="kw">let </span>offset = <span class="self">self</span>.offsets.set[usize::from(haystack[pos])].max;
<a href=#727 id=727 data-nosnippet>727</a> cmp::max(span.start, pos.saturating_sub(usize::from(offset)))
<a href=#728 id=728 data-nosnippet>728</a> })
<a href=#729 id=729 data-nosnippet>729</a> .map_or(Candidate::None, Candidate::PossibleStartOfMatch)
<a href=#730 id=730 data-nosnippet>730</a> }
<a href=#731 id=731 data-nosnippet>731</a>}
<a href=#732 id=732 data-nosnippet>732</a>
<a href=#733 id=733 data-nosnippet>733</a><span class="doccomment">/// A builder for constructing a starting byte prefilter.
<a href=#734 id=734 data-nosnippet>734</a>///
<a href=#735 id=735 data-nosnippet>735</a>/// A starting byte prefilter is a simplistic prefilter that looks for possible
<a href=#736 id=736 data-nosnippet>736</a>/// matches by reporting all positions corresponding to a particular byte. This
<a href=#737 id=737 data-nosnippet>737</a>/// generally only takes affect when there are at most 3 distinct possible
<a href=#738 id=738 data-nosnippet>738</a>/// starting bytes. e.g., the patterns `foo`, `bar`, and `baz` have two
<a href=#739 id=739 data-nosnippet>739</a>/// distinct starting bytes (`f` and `b`), and this prefilter returns all
<a href=#740 id=740 data-nosnippet>740</a>/// occurrences of either `f` or `b`.
<a href=#741 id=741 data-nosnippet>741</a>///
<a href=#742 id=742 data-nosnippet>742</a>/// In some cases, a heuristic frequency analysis may determine that it would
<a href=#743 id=743 data-nosnippet>743</a>/// be better not to use this prefilter even when there are 3 or fewer distinct
<a href=#744 id=744 data-nosnippet>744</a>/// starting bytes.
<a href=#745 id=745 data-nosnippet>745</a></span><span class="attr">#[derive(Clone, Debug)]
<a href=#746 id=746 data-nosnippet>746</a></span><span class="kw">struct </span>StartBytesBuilder {
<a href=#747 id=747 data-nosnippet>747</a> <span class="doccomment">/// Whether this prefilter should account for ASCII case insensitivity or
<a href=#748 id=748 data-nosnippet>748</a> /// not.
<a href=#749 id=749 data-nosnippet>749</a> </span>ascii_case_insensitive: bool,
<a href=#750 id=750 data-nosnippet>750</a> <span class="doccomment">/// The set of starting bytes observed.
<a href=#751 id=751 data-nosnippet>751</a> </span>byteset: Vec&lt;bool&gt;,
<a href=#752 id=752 data-nosnippet>752</a> <span class="doccomment">/// The number of bytes set to true in `byteset`.
<a href=#753 id=753 data-nosnippet>753</a> </span>count: usize,
<a href=#754 id=754 data-nosnippet>754</a> <span class="doccomment">/// The sum of frequency ranks for the rare bytes detected. This is
<a href=#755 id=755 data-nosnippet>755</a> /// intended to give a heuristic notion of how rare the bytes are.
<a href=#756 id=756 data-nosnippet>756</a> </span>rank_sum: u16,
<a href=#757 id=757 data-nosnippet>757</a>}
<a href=#758 id=758 data-nosnippet>758</a>
<a href=#759 id=759 data-nosnippet>759</a><span class="kw">impl </span>StartBytesBuilder {
<a href=#760 id=760 data-nosnippet>760</a> <span class="doccomment">/// Create a new builder for constructing a start byte prefilter.
<a href=#761 id=761 data-nosnippet>761</a> </span><span class="kw">fn </span>new() -&gt; StartBytesBuilder {
<a href=#762 id=762 data-nosnippet>762</a> StartBytesBuilder {
<a href=#763 id=763 data-nosnippet>763</a> ascii_case_insensitive: <span class="bool-val">false</span>,
<a href=#764 id=764 data-nosnippet>764</a> byteset: <span class="macro">vec!</span>[<span class="bool-val">false</span>; <span class="number">256</span>],
<a href=#765 id=765 data-nosnippet>765</a> count: <span class="number">0</span>,
<a href=#766 id=766 data-nosnippet>766</a> rank_sum: <span class="number">0</span>,
<a href=#767 id=767 data-nosnippet>767</a> }
<a href=#768 id=768 data-nosnippet>768</a> }
<a href=#769 id=769 data-nosnippet>769</a>
<a href=#770 id=770 data-nosnippet>770</a> <span class="doccomment">/// Enable ASCII case insensitivity. When set, byte strings added to this
<a href=#771 id=771 data-nosnippet>771</a> /// builder will be interpreted without respect to ASCII case.
<a href=#772 id=772 data-nosnippet>772</a> </span><span class="kw">fn </span>ascii_case_insensitive(<span class="kw-2">mut </span><span class="self">self</span>, yes: bool) -&gt; StartBytesBuilder {
<a href=#773 id=773 data-nosnippet>773</a> <span class="self">self</span>.ascii_case_insensitive = yes;
<a href=#774 id=774 data-nosnippet>774</a> <span class="self">self
<a href=#775 id=775 data-nosnippet>775</a> </span>}
<a href=#776 id=776 data-nosnippet>776</a>
<a href=#777 id=777 data-nosnippet>777</a> <span class="doccomment">/// Build the starting bytes prefilter.
<a href=#778 id=778 data-nosnippet>778</a> ///
<a href=#779 id=779 data-nosnippet>779</a> /// If there are more than 3 distinct starting bytes, or if heuristics
<a href=#780 id=780 data-nosnippet>780</a> /// otherwise determine that this prefilter should not be used, then `None`
<a href=#781 id=781 data-nosnippet>781</a> /// is returned.
<a href=#782 id=782 data-nosnippet>782</a> </span><span class="kw">fn </span>build(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; <span class="prelude-ty">Option</span>&lt;Prefilter&gt; {
<a href=#783 id=783 data-nosnippet>783</a> <span class="attr">#[cfg(feature = <span class="string">"perf-literal"</span>)]
<a href=#784 id=784 data-nosnippet>784</a> </span><span class="kw">fn </span>imp(builder: <span class="kw-2">&amp;</span>StartBytesBuilder) -&gt; <span class="prelude-ty">Option</span>&lt;Prefilter&gt; {
<a href=#785 id=785 data-nosnippet>785</a> <span class="kw">if </span>builder.count &gt; <span class="number">3 </span>{
<a href=#786 id=786 data-nosnippet>786</a> <span class="kw">return </span><span class="prelude-val">None</span>;
<a href=#787 id=787 data-nosnippet>787</a> }
<a href=#788 id=788 data-nosnippet>788</a> <span class="kw">let </span>(<span class="kw-2">mut </span>bytes, <span class="kw-2">mut </span>len) = ([<span class="number">0</span>; <span class="number">3</span>], <span class="number">0</span>);
<a href=#789 id=789 data-nosnippet>789</a> <span class="kw">for </span>b <span class="kw">in </span><span class="number">0</span>..<span class="number">256 </span>{
<a href=#790 id=790 data-nosnippet>790</a> <span class="kw">if </span>!builder.byteset[b] {
<a href=#791 id=791 data-nosnippet>791</a> <span class="kw">continue</span>;
<a href=#792 id=792 data-nosnippet>792</a> }
<a href=#793 id=793 data-nosnippet>793</a> <span class="comment">// We don't handle non-ASCII bytes for now. Getting non-ASCII
<a href=#794 id=794 data-nosnippet>794</a> // bytes right is trickier, since we generally don't want to put
<a href=#795 id=795 data-nosnippet>795</a> // a leading UTF-8 code unit into a prefilter that isn't ASCII,
<a href=#796 id=796 data-nosnippet>796</a> // since they can frequently. Instead, it would be better to use a
<a href=#797 id=797 data-nosnippet>797</a> // continuation byte, but this requires more sophisticated analysis
<a href=#798 id=798 data-nosnippet>798</a> // of the automaton and a richer prefilter API.
<a href=#799 id=799 data-nosnippet>799</a> </span><span class="kw">if </span>b &gt; <span class="number">0x7F </span>{
<a href=#800 id=800 data-nosnippet>800</a> <span class="kw">return </span><span class="prelude-val">None</span>;
<a href=#801 id=801 data-nosnippet>801</a> }
<a href=#802 id=802 data-nosnippet>802</a> bytes[len] = b <span class="kw">as </span>u8;
<a href=#803 id=803 data-nosnippet>803</a> len += <span class="number">1</span>;
<a href=#804 id=804 data-nosnippet>804</a> }
<a href=#805 id=805 data-nosnippet>805</a> <span class="kw">let </span>finder: Arc&lt;<span class="kw">dyn </span>PrefilterI&gt; = <span class="kw">match </span>len {
<a href=#806 id=806 data-nosnippet>806</a> <span class="number">0 </span>=&gt; <span class="kw">return </span><span class="prelude-val">None</span>,
<a href=#807 id=807 data-nosnippet>807</a> <span class="number">1 </span>=&gt; Arc::new(StartBytesOne { byte1: bytes[<span class="number">0</span>] }),
<a href=#808 id=808 data-nosnippet>808</a> <span class="number">2 </span>=&gt; Arc::new(StartBytesTwo {
<a href=#809 id=809 data-nosnippet>809</a> byte1: bytes[<span class="number">0</span>],
<a href=#810 id=810 data-nosnippet>810</a> byte2: bytes[<span class="number">1</span>],
<a href=#811 id=811 data-nosnippet>811</a> }),
<a href=#812 id=812 data-nosnippet>812</a> <span class="number">3 </span>=&gt; Arc::new(StartBytesThree {
<a href=#813 id=813 data-nosnippet>813</a> byte1: bytes[<span class="number">0</span>],
<a href=#814 id=814 data-nosnippet>814</a> byte2: bytes[<span class="number">1</span>],
<a href=#815 id=815 data-nosnippet>815</a> byte3: bytes[<span class="number">2</span>],
<a href=#816 id=816 data-nosnippet>816</a> }),
<a href=#817 id=817 data-nosnippet>817</a> <span class="kw">_ </span>=&gt; <span class="macro">unreachable!</span>(),
<a href=#818 id=818 data-nosnippet>818</a> };
<a href=#819 id=819 data-nosnippet>819</a> <span class="prelude-val">Some</span>(Prefilter { finder, memory_usage: <span class="number">0 </span>})
<a href=#820 id=820 data-nosnippet>820</a> }
<a href=#821 id=821 data-nosnippet>821</a>
<a href=#822 id=822 data-nosnippet>822</a> <span class="attr">#[cfg(not(feature = <span class="string">"perf-literal"</span>))]
<a href=#823 id=823 data-nosnippet>823</a> </span><span class="kw">fn </span>imp(<span class="kw">_</span>: <span class="kw-2">&amp;</span>StartBytesBuilder) -&gt; <span class="prelude-ty">Option</span>&lt;Prefilter&gt; {
<a href=#824 id=824 data-nosnippet>824</a> <span class="prelude-val">None
<a href=#825 id=825 data-nosnippet>825</a> </span>}
<a href=#826 id=826 data-nosnippet>826</a>
<a href=#827 id=827 data-nosnippet>827</a> imp(<span class="self">self</span>)
<a href=#828 id=828 data-nosnippet>828</a> }
<a href=#829 id=829 data-nosnippet>829</a>
<a href=#830 id=830 data-nosnippet>830</a> <span class="doccomment">/// Add a byte string to this builder.
<a href=#831 id=831 data-nosnippet>831</a> ///
<a href=#832 id=832 data-nosnippet>832</a> /// All patterns added to an Aho-Corasick automaton should be added to this
<a href=#833 id=833 data-nosnippet>833</a> /// builder before attempting to construct the prefilter.
<a href=#834 id=834 data-nosnippet>834</a> </span><span class="kw">fn </span>add(<span class="kw-2">&amp;mut </span><span class="self">self</span>, bytes: <span class="kw-2">&amp;</span>[u8]) {
<a href=#835 id=835 data-nosnippet>835</a> <span class="kw">if </span><span class="self">self</span>.count &gt; <span class="number">3 </span>{
<a href=#836 id=836 data-nosnippet>836</a> <span class="kw">return</span>;
<a href=#837 id=837 data-nosnippet>837</a> }
<a href=#838 id=838 data-nosnippet>838</a> <span class="kw">if let </span><span class="prelude-val">Some</span>(<span class="kw-2">&amp;</span>byte) = bytes.first() {
<a href=#839 id=839 data-nosnippet>839</a> <span class="self">self</span>.add_one_byte(byte);
<a href=#840 id=840 data-nosnippet>840</a> <span class="kw">if </span><span class="self">self</span>.ascii_case_insensitive {
<a href=#841 id=841 data-nosnippet>841</a> <span class="self">self</span>.add_one_byte(opposite_ascii_case(byte));
<a href=#842 id=842 data-nosnippet>842</a> }
<a href=#843 id=843 data-nosnippet>843</a> }
<a href=#844 id=844 data-nosnippet>844</a> }
<a href=#845 id=845 data-nosnippet>845</a>
<a href=#846 id=846 data-nosnippet>846</a> <span class="kw">fn </span>add_one_byte(<span class="kw-2">&amp;mut </span><span class="self">self</span>, byte: u8) {
<a href=#847 id=847 data-nosnippet>847</a> <span class="kw">if </span>!<span class="self">self</span>.byteset[byte <span class="kw">as </span>usize] {
<a href=#848 id=848 data-nosnippet>848</a> <span class="self">self</span>.byteset[byte <span class="kw">as </span>usize] = <span class="bool-val">true</span>;
<a href=#849 id=849 data-nosnippet>849</a> <span class="self">self</span>.count += <span class="number">1</span>;
<a href=#850 id=850 data-nosnippet>850</a> <span class="self">self</span>.rank_sum += freq_rank(byte) <span class="kw">as </span>u16;
<a href=#851 id=851 data-nosnippet>851</a> }
<a href=#852 id=852 data-nosnippet>852</a> }
<a href=#853 id=853 data-nosnippet>853</a>}
<a href=#854 id=854 data-nosnippet>854</a>
<a href=#855 id=855 data-nosnippet>855</a><span class="doccomment">/// A prefilter for scanning for a single starting byte.
<a href=#856 id=856 data-nosnippet>856</a></span><span class="attr">#[cfg(feature = <span class="string">"perf-literal"</span>)]
<a href=#857 id=857 data-nosnippet>857</a>#[derive(Clone, Debug)]
<a href=#858 id=858 data-nosnippet>858</a></span><span class="kw">struct </span>StartBytesOne {
<a href=#859 id=859 data-nosnippet>859</a> byte1: u8,
<a href=#860 id=860 data-nosnippet>860</a>}
<a href=#861 id=861 data-nosnippet>861</a>
<a href=#862 id=862 data-nosnippet>862</a><span class="attr">#[cfg(feature = <span class="string">"perf-literal"</span>)]
<a href=#863 id=863 data-nosnippet>863</a></span><span class="kw">impl </span>PrefilterI <span class="kw">for </span>StartBytesOne {
<a href=#864 id=864 data-nosnippet>864</a> <span class="kw">fn </span>find_in(<span class="kw-2">&amp;</span><span class="self">self</span>, haystack: <span class="kw-2">&amp;</span>[u8], span: Span) -&gt; Candidate {
<a href=#865 id=865 data-nosnippet>865</a> memchr::memchr(<span class="self">self</span>.byte1, <span class="kw-2">&amp;</span>haystack[span])
<a href=#866 id=866 data-nosnippet>866</a> .map(|i| span.start + i)
<a href=#867 id=867 data-nosnippet>867</a> .map_or(Candidate::None, Candidate::PossibleStartOfMatch)
<a href=#868 id=868 data-nosnippet>868</a> }
<a href=#869 id=869 data-nosnippet>869</a>}
<a href=#870 id=870 data-nosnippet>870</a>
<a href=#871 id=871 data-nosnippet>871</a><span class="doccomment">/// A prefilter for scanning for two starting bytes.
<a href=#872 id=872 data-nosnippet>872</a></span><span class="attr">#[cfg(feature = <span class="string">"perf-literal"</span>)]
<a href=#873 id=873 data-nosnippet>873</a>#[derive(Clone, Debug)]
<a href=#874 id=874 data-nosnippet>874</a></span><span class="kw">struct </span>StartBytesTwo {
<a href=#875 id=875 data-nosnippet>875</a> byte1: u8,
<a href=#876 id=876 data-nosnippet>876</a> byte2: u8,
<a href=#877 id=877 data-nosnippet>877</a>}
<a href=#878 id=878 data-nosnippet>878</a>
<a href=#879 id=879 data-nosnippet>879</a><span class="attr">#[cfg(feature = <span class="string">"perf-literal"</span>)]
<a href=#880 id=880 data-nosnippet>880</a></span><span class="kw">impl </span>PrefilterI <span class="kw">for </span>StartBytesTwo {
<a href=#881 id=881 data-nosnippet>881</a> <span class="kw">fn </span>find_in(<span class="kw-2">&amp;</span><span class="self">self</span>, haystack: <span class="kw-2">&amp;</span>[u8], span: Span) -&gt; Candidate {
<a href=#882 id=882 data-nosnippet>882</a> memchr::memchr2(<span class="self">self</span>.byte1, <span class="self">self</span>.byte2, <span class="kw-2">&amp;</span>haystack[span])
<a href=#883 id=883 data-nosnippet>883</a> .map(|i| span.start + i)
<a href=#884 id=884 data-nosnippet>884</a> .map_or(Candidate::None, Candidate::PossibleStartOfMatch)
<a href=#885 id=885 data-nosnippet>885</a> }
<a href=#886 id=886 data-nosnippet>886</a>}
<a href=#887 id=887 data-nosnippet>887</a>
<a href=#888 id=888 data-nosnippet>888</a><span class="doccomment">/// A prefilter for scanning for three starting bytes.
<a href=#889 id=889 data-nosnippet>889</a></span><span class="attr">#[cfg(feature = <span class="string">"perf-literal"</span>)]
<a href=#890 id=890 data-nosnippet>890</a>#[derive(Clone, Debug)]
<a href=#891 id=891 data-nosnippet>891</a></span><span class="kw">struct </span>StartBytesThree {
<a href=#892 id=892 data-nosnippet>892</a> byte1: u8,
<a href=#893 id=893 data-nosnippet>893</a> byte2: u8,
<a href=#894 id=894 data-nosnippet>894</a> byte3: u8,
<a href=#895 id=895 data-nosnippet>895</a>}
<a href=#896 id=896 data-nosnippet>896</a>
<a href=#897 id=897 data-nosnippet>897</a><span class="attr">#[cfg(feature = <span class="string">"perf-literal"</span>)]
<a href=#898 id=898 data-nosnippet>898</a></span><span class="kw">impl </span>PrefilterI <span class="kw">for </span>StartBytesThree {
<a href=#899 id=899 data-nosnippet>899</a> <span class="kw">fn </span>find_in(<span class="kw-2">&amp;</span><span class="self">self</span>, haystack: <span class="kw-2">&amp;</span>[u8], span: Span) -&gt; Candidate {
<a href=#900 id=900 data-nosnippet>900</a> memchr::memchr3(<span class="self">self</span>.byte1, <span class="self">self</span>.byte2, <span class="self">self</span>.byte3, <span class="kw-2">&amp;</span>haystack[span])
<a href=#901 id=901 data-nosnippet>901</a> .map(|i| span.start + i)
<a href=#902 id=902 data-nosnippet>902</a> .map_or(Candidate::None, Candidate::PossibleStartOfMatch)
<a href=#903 id=903 data-nosnippet>903</a> }
<a href=#904 id=904 data-nosnippet>904</a>}
<a href=#905 id=905 data-nosnippet>905</a>
<a href=#906 id=906 data-nosnippet>906</a><span class="doccomment">/// If the given byte is an ASCII letter, then return it in the opposite case.
<a href=#907 id=907 data-nosnippet>907</a>/// e.g., Given `b'A'`, this returns `b'a'`, and given `b'a'`, this returns
<a href=#908 id=908 data-nosnippet>908</a>/// `b'A'`. If a non-ASCII letter is given, then the given byte is returned.
<a href=#909 id=909 data-nosnippet>909</a></span><span class="kw">pub</span>(<span class="kw">crate</span>) <span class="kw">fn </span>opposite_ascii_case(b: u8) -&gt; u8 {
<a href=#910 id=910 data-nosnippet>910</a> <span class="kw">if </span><span class="string">b'A' </span>&lt;= b &amp;&amp; b &lt;= <span class="string">b'Z' </span>{
<a href=#911 id=911 data-nosnippet>911</a> b.to_ascii_lowercase()
<a href=#912 id=912 data-nosnippet>912</a> } <span class="kw">else if </span><span class="string">b'a' </span>&lt;= b &amp;&amp; b &lt;= <span class="string">b'z' </span>{
<a href=#913 id=913 data-nosnippet>913</a> b.to_ascii_uppercase()
<a href=#914 id=914 data-nosnippet>914</a> } <span class="kw">else </span>{
<a href=#915 id=915 data-nosnippet>915</a> b
<a href=#916 id=916 data-nosnippet>916</a> }
<a href=#917 id=917 data-nosnippet>917</a>}
<a href=#918 id=918 data-nosnippet>918</a>
<a href=#919 id=919 data-nosnippet>919</a><span class="doccomment">/// Return the frequency rank of the given byte. The higher the rank, the more
<a href=#920 id=920 data-nosnippet>920</a>/// common the byte (heuristically speaking).
<a href=#921 id=921 data-nosnippet>921</a></span><span class="kw">fn </span>freq_rank(b: u8) -&gt; u8 {
<a href=#922 id=922 data-nosnippet>922</a> <span class="kw">use </span><span class="kw">crate</span>::util::byte_frequencies::BYTE_FREQUENCIES;
<a href=#923 id=923 data-nosnippet>923</a> BYTE_FREQUENCIES[b <span class="kw">as </span>usize]
<a href=#924 id=924 data-nosnippet>924</a>}
</code></pre></div></section></main></body></html>

View File

@@ -0,0 +1,760 @@
<!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 `/home/newkirk/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/aho-corasick-1.1.4/src/util/primitives.rs`."><title>primitives.rs - source</title><script>if(window.location.protocol!=="file:")document.head.insertAdjacentHTML("beforeend","SourceSerif4-Regular-6b053e98.ttf.woff2,FiraSans-Italic-81dc35de.woff2,FiraSans-Regular-0fe48ade.woff2,FiraSans-MediumItalic-ccf7e434.woff2,FiraSans-Medium-e1aa3f0a.woff2,SourceCodePro-Regular-8badfe75.ttf.woff2,SourceCodePro-Semibold-aa29a496.ttf.woff2".split(",").map(f=>`<link rel="preload" as="font" type="font/woff2"href="../../../static.files/${f}">`).join(""))</script><link rel="stylesheet" href="../../../static.files/normalize-9960930a.css"><link rel="stylesheet" href="../../../static.files/rustdoc-ca0dd0c4.css"><meta name="rustdoc-vars" data-root-path="../../../" data-static-root-path="../../../static.files/" data-current-crate="aho_corasick" data-themes="" data-resource-suffix="" data-rustdoc-version="1.93.1 (01f6ddf75 2026-02-11) (Arch Linux rust 1:1.93.1-1)" data-channel="1.93.1" data-search-js="search-9e2438ea.js" data-stringdex-js="stringdex-a3946164.js" data-settings-js="settings-c38705f0.js" ><script src="../../../static.files/storage-e2aeef58.js"></script><script defer src="../../../static.files/src-script-813739b1.js"></script><script defer src="../../../src-files.js"></script><script defer src="../../../static.files/main-a410ff4d.js"></script><noscript><link rel="stylesheet" href="../../../static.files/noscript-263c88ec.css"></noscript><link rel="alternate icon" type="image/png" href="../../../static.files/favicon-32x32-eab170b8.png"><link rel="icon" type="image/svg+xml" href="../../../static.files/favicon-044be391.svg"></head><body class="rustdoc src"><!--[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="src-sidebar-title"><h2>Files</h2></div></nav><div class="sidebar-resizer" title="Drag to resize sidebar"></div><main><section id="main-content" class="content"><div class="main-heading"><h1><div class="sub-heading">aho_corasick/util/</div>primitives.rs</h1><rustdoc-toolbar></rustdoc-toolbar></div><div class="example-wrap digits-3"><pre class="rust"><code><a href=#1 id=1 data-nosnippet>1</a><span class="doccomment">/*!
<a href=#2 id=2 data-nosnippet>2</a>Lower level primitive types that are useful in a variety of circumstances.
<a href=#3 id=3 data-nosnippet>3</a>
<a href=#4 id=4 data-nosnippet>4</a># Overview
<a href=#5 id=5 data-nosnippet>5</a>
<a href=#6 id=6 data-nosnippet>6</a>This list represents the principle types in this module and briefly describes
<a href=#7 id=7 data-nosnippet>7</a>when you might want to use them.
<a href=#8 id=8 data-nosnippet>8</a>
<a href=#9 id=9 data-nosnippet>9</a>* [`PatternID`] - A type that represents the identifier of a regex pattern.
<a href=#10 id=10 data-nosnippet>10</a>This is probably the most widely used type in this module (which is why it's
<a href=#11 id=11 data-nosnippet>11</a>also re-exported in the crate root).
<a href=#12 id=12 data-nosnippet>12</a>* [`StateID`] - A type the represents the identifier of a finite automaton
<a href=#13 id=13 data-nosnippet>13</a>state. This is used for both NFAs and DFAs, with the notable exception of
<a href=#14 id=14 data-nosnippet>14</a>the hybrid NFA/DFA. (The hybrid NFA/DFA uses a special purpose "lazy" state
<a href=#15 id=15 data-nosnippet>15</a>identifier.)
<a href=#16 id=16 data-nosnippet>16</a>* [`SmallIndex`] - The internal representation of both a `PatternID` and a
<a href=#17 id=17 data-nosnippet>17</a>`StateID`. Its purpose is to serve as a type that can index memory without
<a href=#18 id=18 data-nosnippet>18</a>being as big as a `usize` on 64-bit targets. The main idea behind this type
<a href=#19 id=19 data-nosnippet>19</a>is that there are many things in regex engines that will, in practice, never
<a href=#20 id=20 data-nosnippet>20</a>overflow a 32-bit integer. (For example, like the number of patterns in a regex
<a href=#21 id=21 data-nosnippet>21</a>or the number of states in an NFA.) Thus, a `SmallIndex` can be used to index
<a href=#22 id=22 data-nosnippet>22</a>memory without peppering `as` casts everywhere. Moreover, it forces callers
<a href=#23 id=23 data-nosnippet>23</a>to handle errors in the case where, somehow, the value would otherwise overflow
<a href=#24 id=24 data-nosnippet>24</a>either a 32-bit integer or a `usize` (e.g., on 16-bit targets).
<a href=#25 id=25 data-nosnippet>25</a>*/
<a href=#26 id=26 data-nosnippet>26</a>
<a href=#27 id=27 data-nosnippet>27</a></span><span class="comment">// The macro we use to define some types below adds methods that we don't
<a href=#28 id=28 data-nosnippet>28</a>// use on some of the types. There isn't much, so we just squash the warning.
<a href=#29 id=29 data-nosnippet>29</a></span><span class="attr">#![allow(dead_code)]
<a href=#30 id=30 data-nosnippet>30</a>
<a href=#31 id=31 data-nosnippet>31</a></span><span class="kw">use </span>alloc::vec::Vec;
<a href=#32 id=32 data-nosnippet>32</a>
<a href=#33 id=33 data-nosnippet>33</a><span class="kw">use </span><span class="kw">crate</span>::util::int::{Usize, U16, U32, U64};
<a href=#34 id=34 data-nosnippet>34</a>
<a href=#35 id=35 data-nosnippet>35</a><span class="doccomment">/// A type that represents a "small" index.
<a href=#36 id=36 data-nosnippet>36</a>///
<a href=#37 id=37 data-nosnippet>37</a>/// The main idea of this type is to provide something that can index memory,
<a href=#38 id=38 data-nosnippet>38</a>/// but uses less memory than `usize` on 64-bit systems. Specifically, its
<a href=#39 id=39 data-nosnippet>39</a>/// representation is always a `u32` and has `repr(transparent)` enabled. (So
<a href=#40 id=40 data-nosnippet>40</a>/// it is safe to transmute between a `u32` and a `SmallIndex`.)
<a href=#41 id=41 data-nosnippet>41</a>///
<a href=#42 id=42 data-nosnippet>42</a>/// A small index is typically useful in cases where there is no practical way
<a href=#43 id=43 data-nosnippet>43</a>/// that the index will overflow a 32-bit integer. A good example of this is
<a href=#44 id=44 data-nosnippet>44</a>/// an NFA state. If you could somehow build an NFA with `2^30` states, its
<a href=#45 id=45 data-nosnippet>45</a>/// memory usage would be exorbitant and its runtime execution would be so
<a href=#46 id=46 data-nosnippet>46</a>/// slow as to be completely worthless. Therefore, this crate generally deems
<a href=#47 id=47 data-nosnippet>47</a>/// it acceptable to return an error if it would otherwise build an NFA that
<a href=#48 id=48 data-nosnippet>48</a>/// requires a slice longer than what a 32-bit integer can index. In exchange,
<a href=#49 id=49 data-nosnippet>49</a>/// we can use 32-bit indices instead of 64-bit indices in various places.
<a href=#50 id=50 data-nosnippet>50</a>///
<a href=#51 id=51 data-nosnippet>51</a>/// This type ensures this by providing a constructor that will return an error
<a href=#52 id=52 data-nosnippet>52</a>/// if its argument cannot fit into the type. This makes it much easier to
<a href=#53 id=53 data-nosnippet>53</a>/// handle these sorts of boundary cases that are otherwise extremely subtle.
<a href=#54 id=54 data-nosnippet>54</a>///
<a href=#55 id=55 data-nosnippet>55</a>/// On all targets, this type guarantees that its value will fit in a `u32`,
<a href=#56 id=56 data-nosnippet>56</a>/// `i32`, `usize` and an `isize`. This means that on 16-bit targets, for
<a href=#57 id=57 data-nosnippet>57</a>/// example, this type's maximum value will never overflow an `isize`,
<a href=#58 id=58 data-nosnippet>58</a>/// which means it will never overflow a `i16` even though its internal
<a href=#59 id=59 data-nosnippet>59</a>/// representation is still a `u32`.
<a href=#60 id=60 data-nosnippet>60</a>///
<a href=#61 id=61 data-nosnippet>61</a>/// The purpose for making the type fit into even signed integer types like
<a href=#62 id=62 data-nosnippet>62</a>/// `isize` is to guarantee that the difference between any two small indices
<a href=#63 id=63 data-nosnippet>63</a>/// is itself also a small index. This is useful in certain contexts, e.g.,
<a href=#64 id=64 data-nosnippet>64</a>/// for delta encoding.
<a href=#65 id=65 data-nosnippet>65</a>///
<a href=#66 id=66 data-nosnippet>66</a>/// # Other types
<a href=#67 id=67 data-nosnippet>67</a>///
<a href=#68 id=68 data-nosnippet>68</a>/// The following types wrap `SmallIndex` to provide a more focused use case:
<a href=#69 id=69 data-nosnippet>69</a>///
<a href=#70 id=70 data-nosnippet>70</a>/// * [`PatternID`] is for representing the identifiers of patterns.
<a href=#71 id=71 data-nosnippet>71</a>/// * [`StateID`] is for representing the identifiers of states in finite
<a href=#72 id=72 data-nosnippet>72</a>/// automata. It is used for both NFAs and DFAs.
<a href=#73 id=73 data-nosnippet>73</a>///
<a href=#74 id=74 data-nosnippet>74</a>/// # Representation
<a href=#75 id=75 data-nosnippet>75</a>///
<a href=#76 id=76 data-nosnippet>76</a>/// This type is always represented internally by a `u32` and is marked as
<a href=#77 id=77 data-nosnippet>77</a>/// `repr(transparent)`. Thus, this type always has the same representation as
<a href=#78 id=78 data-nosnippet>78</a>/// a `u32`. It is thus safe to transmute between a `u32` and a `SmallIndex`.
<a href=#79 id=79 data-nosnippet>79</a>///
<a href=#80 id=80 data-nosnippet>80</a>/// # Indexing
<a href=#81 id=81 data-nosnippet>81</a>///
<a href=#82 id=82 data-nosnippet>82</a>/// For convenience, callers may use a `SmallIndex` to index slices.
<a href=#83 id=83 data-nosnippet>83</a>///
<a href=#84 id=84 data-nosnippet>84</a>/// # Safety
<a href=#85 id=85 data-nosnippet>85</a>///
<a href=#86 id=86 data-nosnippet>86</a>/// While a `SmallIndex` is meant to guarantee that its value fits into `usize`
<a href=#87 id=87 data-nosnippet>87</a>/// without using as much space as a `usize` on all targets, callers must
<a href=#88 id=88 data-nosnippet>88</a>/// not rely on this property for safety. Callers may choose to rely on this
<a href=#89 id=89 data-nosnippet>89</a>/// property for correctness however. For example, creating a `SmallIndex` with
<a href=#90 id=90 data-nosnippet>90</a>/// an invalid value can be done in entirely safe code. This may in turn result
<a href=#91 id=91 data-nosnippet>91</a>/// in panics or silent logical errors.
<a href=#92 id=92 data-nosnippet>92</a></span><span class="attr">#[derive(
<a href=#93 id=93 data-nosnippet>93</a> Clone, Copy, Debug, Default, Eq, Hash, PartialEq, PartialOrd, Ord,
<a href=#94 id=94 data-nosnippet>94</a>)]
<a href=#95 id=95 data-nosnippet>95</a>#[repr(transparent)]
<a href=#96 id=96 data-nosnippet>96</a></span><span class="kw">pub</span>(<span class="kw">crate</span>) <span class="kw">struct </span>SmallIndex(u32);
<a href=#97 id=97 data-nosnippet>97</a>
<a href=#98 id=98 data-nosnippet>98</a><span class="kw">impl </span>SmallIndex {
<a href=#99 id=99 data-nosnippet>99</a> <span class="doccomment">/// The maximum index value.
<a href=#100 id=100 data-nosnippet>100</a> </span><span class="attr">#[cfg(any(target_pointer_width = <span class="string">"32"</span>, target_pointer_width = <span class="string">"64"</span>))]
<a href=#101 id=101 data-nosnippet>101</a> </span><span class="kw">pub const </span>MAX: SmallIndex =
<a href=#102 id=102 data-nosnippet>102</a> <span class="comment">// FIXME: Use as_usize() once const functions in traits are stable.
<a href=#103 id=103 data-nosnippet>103</a> </span>SmallIndex::new_unchecked(core::i32::MAX <span class="kw">as </span>usize - <span class="number">1</span>);
<a href=#104 id=104 data-nosnippet>104</a>
<a href=#105 id=105 data-nosnippet>105</a> <span class="doccomment">/// The maximum index value.
<a href=#106 id=106 data-nosnippet>106</a> </span><span class="attr">#[cfg(target_pointer_width = <span class="string">"16"</span>)]
<a href=#107 id=107 data-nosnippet>107</a> </span><span class="kw">pub const </span>MAX: SmallIndex =
<a href=#108 id=108 data-nosnippet>108</a> SmallIndex::new_unchecked(core::isize::MAX - <span class="number">1</span>);
<a href=#109 id=109 data-nosnippet>109</a>
<a href=#110 id=110 data-nosnippet>110</a> <span class="doccomment">/// The total number of values that can be represented as a small index.
<a href=#111 id=111 data-nosnippet>111</a> </span><span class="kw">pub const </span>LIMIT: usize = SmallIndex::MAX.as_usize() + <span class="number">1</span>;
<a href=#112 id=112 data-nosnippet>112</a>
<a href=#113 id=113 data-nosnippet>113</a> <span class="doccomment">/// The zero index value.
<a href=#114 id=114 data-nosnippet>114</a> </span><span class="kw">pub const </span>ZERO: SmallIndex = SmallIndex::new_unchecked(<span class="number">0</span>);
<a href=#115 id=115 data-nosnippet>115</a>
<a href=#116 id=116 data-nosnippet>116</a> <span class="doccomment">/// The number of bytes that a single small index uses in memory.
<a href=#117 id=117 data-nosnippet>117</a> </span><span class="kw">pub const </span>SIZE: usize = core::mem::size_of::&lt;SmallIndex&gt;();
<a href=#118 id=118 data-nosnippet>118</a>
<a href=#119 id=119 data-nosnippet>119</a> <span class="doccomment">/// Create a new small index.
<a href=#120 id=120 data-nosnippet>120</a> ///
<a href=#121 id=121 data-nosnippet>121</a> /// If the given index exceeds [`SmallIndex::MAX`], then this returns
<a href=#122 id=122 data-nosnippet>122</a> /// an error.
<a href=#123 id=123 data-nosnippet>123</a> </span><span class="attr">#[inline]
<a href=#124 id=124 data-nosnippet>124</a> </span><span class="kw">pub fn </span>new(index: usize) -&gt; <span class="prelude-ty">Result</span>&lt;SmallIndex, SmallIndexError&gt; {
<a href=#125 id=125 data-nosnippet>125</a> SmallIndex::try_from(index)
<a href=#126 id=126 data-nosnippet>126</a> }
<a href=#127 id=127 data-nosnippet>127</a>
<a href=#128 id=128 data-nosnippet>128</a> <span class="doccomment">/// Create a new small index without checking whether the given value
<a href=#129 id=129 data-nosnippet>129</a> /// exceeds [`SmallIndex::MAX`].
<a href=#130 id=130 data-nosnippet>130</a> ///
<a href=#131 id=131 data-nosnippet>131</a> /// Using this routine with an invalid index value will result in
<a href=#132 id=132 data-nosnippet>132</a> /// unspecified behavior, but *not* undefined behavior. In particular, an
<a href=#133 id=133 data-nosnippet>133</a> /// invalid index value is likely to cause panics or possibly even silent
<a href=#134 id=134 data-nosnippet>134</a> /// logical errors.
<a href=#135 id=135 data-nosnippet>135</a> ///
<a href=#136 id=136 data-nosnippet>136</a> /// Callers must never rely on a `SmallIndex` to be within a certain range
<a href=#137 id=137 data-nosnippet>137</a> /// for memory safety.
<a href=#138 id=138 data-nosnippet>138</a> </span><span class="attr">#[inline]
<a href=#139 id=139 data-nosnippet>139</a> </span><span class="kw">pub const fn </span>new_unchecked(index: usize) -&gt; SmallIndex {
<a href=#140 id=140 data-nosnippet>140</a> <span class="comment">// FIXME: Use as_u32() once const functions in traits are stable.
<a href=#141 id=141 data-nosnippet>141</a> </span>SmallIndex::from_u32_unchecked(index <span class="kw">as </span>u32)
<a href=#142 id=142 data-nosnippet>142</a> }
<a href=#143 id=143 data-nosnippet>143</a>
<a href=#144 id=144 data-nosnippet>144</a> <span class="doccomment">/// Create a new small index from a `u32` without checking whether the
<a href=#145 id=145 data-nosnippet>145</a> /// given value exceeds [`SmallIndex::MAX`].
<a href=#146 id=146 data-nosnippet>146</a> ///
<a href=#147 id=147 data-nosnippet>147</a> /// Using this routine with an invalid index value will result in
<a href=#148 id=148 data-nosnippet>148</a> /// unspecified behavior, but *not* undefined behavior. In particular, an
<a href=#149 id=149 data-nosnippet>149</a> /// invalid index value is likely to cause panics or possibly even silent
<a href=#150 id=150 data-nosnippet>150</a> /// logical errors.
<a href=#151 id=151 data-nosnippet>151</a> ///
<a href=#152 id=152 data-nosnippet>152</a> /// Callers must never rely on a `SmallIndex` to be within a certain range
<a href=#153 id=153 data-nosnippet>153</a> /// for memory safety.
<a href=#154 id=154 data-nosnippet>154</a> </span><span class="attr">#[inline]
<a href=#155 id=155 data-nosnippet>155</a> </span><span class="kw">pub const fn </span>from_u32_unchecked(index: u32) -&gt; SmallIndex {
<a href=#156 id=156 data-nosnippet>156</a> SmallIndex(index)
<a href=#157 id=157 data-nosnippet>157</a> }
<a href=#158 id=158 data-nosnippet>158</a>
<a href=#159 id=159 data-nosnippet>159</a> <span class="doccomment">/// Like [`SmallIndex::new`], but panics if the given index is not valid.
<a href=#160 id=160 data-nosnippet>160</a> </span><span class="attr">#[inline]
<a href=#161 id=161 data-nosnippet>161</a> </span><span class="kw">pub fn </span>must(index: usize) -&gt; SmallIndex {
<a href=#162 id=162 data-nosnippet>162</a> SmallIndex::new(index).expect(<span class="string">"invalid small index"</span>)
<a href=#163 id=163 data-nosnippet>163</a> }
<a href=#164 id=164 data-nosnippet>164</a>
<a href=#165 id=165 data-nosnippet>165</a> <span class="doccomment">/// Return this small index as a `usize`. This is guaranteed to never
<a href=#166 id=166 data-nosnippet>166</a> /// overflow `usize`.
<a href=#167 id=167 data-nosnippet>167</a> </span><span class="attr">#[inline]
<a href=#168 id=168 data-nosnippet>168</a> </span><span class="kw">pub const fn </span>as_usize(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; usize {
<a href=#169 id=169 data-nosnippet>169</a> <span class="comment">// FIXME: Use as_usize() once const functions in traits are stable.
<a href=#170 id=170 data-nosnippet>170</a> </span><span class="self">self</span>.<span class="number">0 </span><span class="kw">as </span>usize
<a href=#171 id=171 data-nosnippet>171</a> }
<a href=#172 id=172 data-nosnippet>172</a>
<a href=#173 id=173 data-nosnippet>173</a> <span class="doccomment">/// Return this small index as a `u64`. This is guaranteed to never
<a href=#174 id=174 data-nosnippet>174</a> /// overflow.
<a href=#175 id=175 data-nosnippet>175</a> </span><span class="attr">#[inline]
<a href=#176 id=176 data-nosnippet>176</a> </span><span class="kw">pub const fn </span>as_u64(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; u64 {
<a href=#177 id=177 data-nosnippet>177</a> <span class="comment">// FIXME: Use u64::from() once const functions in traits are stable.
<a href=#178 id=178 data-nosnippet>178</a> </span><span class="self">self</span>.<span class="number">0 </span><span class="kw">as </span>u64
<a href=#179 id=179 data-nosnippet>179</a> }
<a href=#180 id=180 data-nosnippet>180</a>
<a href=#181 id=181 data-nosnippet>181</a> <span class="doccomment">/// Return the internal `u32` of this small index. This is guaranteed to
<a href=#182 id=182 data-nosnippet>182</a> /// never overflow `u32`.
<a href=#183 id=183 data-nosnippet>183</a> </span><span class="attr">#[inline]
<a href=#184 id=184 data-nosnippet>184</a> </span><span class="kw">pub const fn </span>as_u32(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; u32 {
<a href=#185 id=185 data-nosnippet>185</a> <span class="self">self</span>.<span class="number">0
<a href=#186 id=186 data-nosnippet>186</a> </span>}
<a href=#187 id=187 data-nosnippet>187</a>
<a href=#188 id=188 data-nosnippet>188</a> <span class="doccomment">/// Return the internal `u32` of this small index represented as an `i32`.
<a href=#189 id=189 data-nosnippet>189</a> /// This is guaranteed to never overflow an `i32`.
<a href=#190 id=190 data-nosnippet>190</a> </span><span class="attr">#[inline]
<a href=#191 id=191 data-nosnippet>191</a> </span><span class="kw">pub const fn </span>as_i32(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; i32 {
<a href=#192 id=192 data-nosnippet>192</a> <span class="comment">// This is OK because we guarantee that our max value is &lt;= i32::MAX.
<a href=#193 id=193 data-nosnippet>193</a> </span><span class="self">self</span>.<span class="number">0 </span><span class="kw">as </span>i32
<a href=#194 id=194 data-nosnippet>194</a> }
<a href=#195 id=195 data-nosnippet>195</a>
<a href=#196 id=196 data-nosnippet>196</a> <span class="doccomment">/// Returns one more than this small index as a usize.
<a href=#197 id=197 data-nosnippet>197</a> ///
<a href=#198 id=198 data-nosnippet>198</a> /// Since a small index has constraints on its maximum value, adding `1` to
<a href=#199 id=199 data-nosnippet>199</a> /// it will always fit in a `usize`, `isize`, `u32` and a `i32`.
<a href=#200 id=200 data-nosnippet>200</a> </span><span class="attr">#[inline]
<a href=#201 id=201 data-nosnippet>201</a> </span><span class="kw">pub fn </span>one_more(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; usize {
<a href=#202 id=202 data-nosnippet>202</a> <span class="self">self</span>.as_usize() + <span class="number">1
<a href=#203 id=203 data-nosnippet>203</a> </span>}
<a href=#204 id=204 data-nosnippet>204</a>
<a href=#205 id=205 data-nosnippet>205</a> <span class="doccomment">/// Decode this small index from the bytes given using the native endian
<a href=#206 id=206 data-nosnippet>206</a> /// byte order for the current target.
<a href=#207 id=207 data-nosnippet>207</a> ///
<a href=#208 id=208 data-nosnippet>208</a> /// If the decoded integer is not representable as a small index for the
<a href=#209 id=209 data-nosnippet>209</a> /// current target, then this returns an error.
<a href=#210 id=210 data-nosnippet>210</a> </span><span class="attr">#[inline]
<a href=#211 id=211 data-nosnippet>211</a> </span><span class="kw">pub fn </span>from_ne_bytes(
<a href=#212 id=212 data-nosnippet>212</a> bytes: [u8; <span class="number">4</span>],
<a href=#213 id=213 data-nosnippet>213</a> ) -&gt; <span class="prelude-ty">Result</span>&lt;SmallIndex, SmallIndexError&gt; {
<a href=#214 id=214 data-nosnippet>214</a> <span class="kw">let </span>id = u32::from_ne_bytes(bytes);
<a href=#215 id=215 data-nosnippet>215</a> <span class="kw">if </span>id &gt; SmallIndex::MAX.as_u32() {
<a href=#216 id=216 data-nosnippet>216</a> <span class="kw">return </span><span class="prelude-val">Err</span>(SmallIndexError { attempted: u64::from(id) });
<a href=#217 id=217 data-nosnippet>217</a> }
<a href=#218 id=218 data-nosnippet>218</a> <span class="prelude-val">Ok</span>(SmallIndex::new_unchecked(id.as_usize()))
<a href=#219 id=219 data-nosnippet>219</a> }
<a href=#220 id=220 data-nosnippet>220</a>
<a href=#221 id=221 data-nosnippet>221</a> <span class="doccomment">/// Decode this small index from the bytes given using the native endian
<a href=#222 id=222 data-nosnippet>222</a> /// byte order for the current target.
<a href=#223 id=223 data-nosnippet>223</a> ///
<a href=#224 id=224 data-nosnippet>224</a> /// This is analogous to [`SmallIndex::new_unchecked`] in that is does not
<a href=#225 id=225 data-nosnippet>225</a> /// check whether the decoded integer is representable as a small index.
<a href=#226 id=226 data-nosnippet>226</a> </span><span class="attr">#[inline]
<a href=#227 id=227 data-nosnippet>227</a> </span><span class="kw">pub fn </span>from_ne_bytes_unchecked(bytes: [u8; <span class="number">4</span>]) -&gt; SmallIndex {
<a href=#228 id=228 data-nosnippet>228</a> SmallIndex::new_unchecked(u32::from_ne_bytes(bytes).as_usize())
<a href=#229 id=229 data-nosnippet>229</a> }
<a href=#230 id=230 data-nosnippet>230</a>
<a href=#231 id=231 data-nosnippet>231</a> <span class="doccomment">/// Return the underlying small index integer as raw bytes in native endian
<a href=#232 id=232 data-nosnippet>232</a> /// format.
<a href=#233 id=233 data-nosnippet>233</a> </span><span class="attr">#[inline]
<a href=#234 id=234 data-nosnippet>234</a> </span><span class="kw">pub fn </span>to_ne_bytes(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; [u8; <span class="number">4</span>] {
<a href=#235 id=235 data-nosnippet>235</a> <span class="self">self</span>.<span class="number">0</span>.to_ne_bytes()
<a href=#236 id=236 data-nosnippet>236</a> }
<a href=#237 id=237 data-nosnippet>237</a>}
<a href=#238 id=238 data-nosnippet>238</a>
<a href=#239 id=239 data-nosnippet>239</a><span class="kw">impl</span>&lt;T&gt; core::ops::Index&lt;SmallIndex&gt; <span class="kw">for </span>[T] {
<a href=#240 id=240 data-nosnippet>240</a> <span class="kw">type </span>Output = T;
<a href=#241 id=241 data-nosnippet>241</a>
<a href=#242 id=242 data-nosnippet>242</a> <span class="attr">#[inline]
<a href=#243 id=243 data-nosnippet>243</a> </span><span class="kw">fn </span>index(<span class="kw-2">&amp;</span><span class="self">self</span>, index: SmallIndex) -&gt; <span class="kw-2">&amp;</span>T {
<a href=#244 id=244 data-nosnippet>244</a> <span class="kw-2">&amp;</span><span class="self">self</span>[index.as_usize()]
<a href=#245 id=245 data-nosnippet>245</a> }
<a href=#246 id=246 data-nosnippet>246</a>}
<a href=#247 id=247 data-nosnippet>247</a>
<a href=#248 id=248 data-nosnippet>248</a><span class="kw">impl</span>&lt;T&gt; core::ops::IndexMut&lt;SmallIndex&gt; <span class="kw">for </span>[T] {
<a href=#249 id=249 data-nosnippet>249</a> <span class="attr">#[inline]
<a href=#250 id=250 data-nosnippet>250</a> </span><span class="kw">fn </span>index_mut(<span class="kw-2">&amp;mut </span><span class="self">self</span>, index: SmallIndex) -&gt; <span class="kw-2">&amp;mut </span>T {
<a href=#251 id=251 data-nosnippet>251</a> <span class="kw-2">&amp;mut </span><span class="self">self</span>[index.as_usize()]
<a href=#252 id=252 data-nosnippet>252</a> }
<a href=#253 id=253 data-nosnippet>253</a>}
<a href=#254 id=254 data-nosnippet>254</a>
<a href=#255 id=255 data-nosnippet>255</a><span class="kw">impl</span>&lt;T&gt; core::ops::Index&lt;SmallIndex&gt; <span class="kw">for </span>Vec&lt;T&gt; {
<a href=#256 id=256 data-nosnippet>256</a> <span class="kw">type </span>Output = T;
<a href=#257 id=257 data-nosnippet>257</a>
<a href=#258 id=258 data-nosnippet>258</a> <span class="attr">#[inline]
<a href=#259 id=259 data-nosnippet>259</a> </span><span class="kw">fn </span>index(<span class="kw-2">&amp;</span><span class="self">self</span>, index: SmallIndex) -&gt; <span class="kw-2">&amp;</span>T {
<a href=#260 id=260 data-nosnippet>260</a> <span class="kw-2">&amp;</span><span class="self">self</span>[index.as_usize()]
<a href=#261 id=261 data-nosnippet>261</a> }
<a href=#262 id=262 data-nosnippet>262</a>}
<a href=#263 id=263 data-nosnippet>263</a>
<a href=#264 id=264 data-nosnippet>264</a><span class="kw">impl</span>&lt;T&gt; core::ops::IndexMut&lt;SmallIndex&gt; <span class="kw">for </span>Vec&lt;T&gt; {
<a href=#265 id=265 data-nosnippet>265</a> <span class="attr">#[inline]
<a href=#266 id=266 data-nosnippet>266</a> </span><span class="kw">fn </span>index_mut(<span class="kw-2">&amp;mut </span><span class="self">self</span>, index: SmallIndex) -&gt; <span class="kw-2">&amp;mut </span>T {
<a href=#267 id=267 data-nosnippet>267</a> <span class="kw-2">&amp;mut </span><span class="self">self</span>[index.as_usize()]
<a href=#268 id=268 data-nosnippet>268</a> }
<a href=#269 id=269 data-nosnippet>269</a>}
<a href=#270 id=270 data-nosnippet>270</a>
<a href=#271 id=271 data-nosnippet>271</a><span class="kw">impl </span>From&lt;StateID&gt; <span class="kw">for </span>SmallIndex {
<a href=#272 id=272 data-nosnippet>272</a> <span class="kw">fn </span>from(sid: StateID) -&gt; SmallIndex {
<a href=#273 id=273 data-nosnippet>273</a> sid.<span class="number">0
<a href=#274 id=274 data-nosnippet>274</a> </span>}
<a href=#275 id=275 data-nosnippet>275</a>}
<a href=#276 id=276 data-nosnippet>276</a>
<a href=#277 id=277 data-nosnippet>277</a><span class="kw">impl </span>From&lt;PatternID&gt; <span class="kw">for </span>SmallIndex {
<a href=#278 id=278 data-nosnippet>278</a> <span class="kw">fn </span>from(pid: PatternID) -&gt; SmallIndex {
<a href=#279 id=279 data-nosnippet>279</a> pid.<span class="number">0
<a href=#280 id=280 data-nosnippet>280</a> </span>}
<a href=#281 id=281 data-nosnippet>281</a>}
<a href=#282 id=282 data-nosnippet>282</a>
<a href=#283 id=283 data-nosnippet>283</a><span class="kw">impl </span>From&lt;u8&gt; <span class="kw">for </span>SmallIndex {
<a href=#284 id=284 data-nosnippet>284</a> <span class="kw">fn </span>from(index: u8) -&gt; SmallIndex {
<a href=#285 id=285 data-nosnippet>285</a> SmallIndex::new_unchecked(usize::from(index))
<a href=#286 id=286 data-nosnippet>286</a> }
<a href=#287 id=287 data-nosnippet>287</a>}
<a href=#288 id=288 data-nosnippet>288</a>
<a href=#289 id=289 data-nosnippet>289</a><span class="kw">impl </span>TryFrom&lt;u16&gt; <span class="kw">for </span>SmallIndex {
<a href=#290 id=290 data-nosnippet>290</a> <span class="kw">type </span>Error = SmallIndexError;
<a href=#291 id=291 data-nosnippet>291</a>
<a href=#292 id=292 data-nosnippet>292</a> <span class="kw">fn </span>try_from(index: u16) -&gt; <span class="prelude-ty">Result</span>&lt;SmallIndex, SmallIndexError&gt; {
<a href=#293 id=293 data-nosnippet>293</a> <span class="kw">if </span>u32::from(index) &gt; SmallIndex::MAX.as_u32() {
<a href=#294 id=294 data-nosnippet>294</a> <span class="kw">return </span><span class="prelude-val">Err</span>(SmallIndexError { attempted: u64::from(index) });
<a href=#295 id=295 data-nosnippet>295</a> }
<a href=#296 id=296 data-nosnippet>296</a> <span class="prelude-val">Ok</span>(SmallIndex::new_unchecked(index.as_usize()))
<a href=#297 id=297 data-nosnippet>297</a> }
<a href=#298 id=298 data-nosnippet>298</a>}
<a href=#299 id=299 data-nosnippet>299</a>
<a href=#300 id=300 data-nosnippet>300</a><span class="kw">impl </span>TryFrom&lt;u32&gt; <span class="kw">for </span>SmallIndex {
<a href=#301 id=301 data-nosnippet>301</a> <span class="kw">type </span>Error = SmallIndexError;
<a href=#302 id=302 data-nosnippet>302</a>
<a href=#303 id=303 data-nosnippet>303</a> <span class="kw">fn </span>try_from(index: u32) -&gt; <span class="prelude-ty">Result</span>&lt;SmallIndex, SmallIndexError&gt; {
<a href=#304 id=304 data-nosnippet>304</a> <span class="kw">if </span>index &gt; SmallIndex::MAX.as_u32() {
<a href=#305 id=305 data-nosnippet>305</a> <span class="kw">return </span><span class="prelude-val">Err</span>(SmallIndexError { attempted: u64::from(index) });
<a href=#306 id=306 data-nosnippet>306</a> }
<a href=#307 id=307 data-nosnippet>307</a> <span class="prelude-val">Ok</span>(SmallIndex::new_unchecked(index.as_usize()))
<a href=#308 id=308 data-nosnippet>308</a> }
<a href=#309 id=309 data-nosnippet>309</a>}
<a href=#310 id=310 data-nosnippet>310</a>
<a href=#311 id=311 data-nosnippet>311</a><span class="kw">impl </span>TryFrom&lt;u64&gt; <span class="kw">for </span>SmallIndex {
<a href=#312 id=312 data-nosnippet>312</a> <span class="kw">type </span>Error = SmallIndexError;
<a href=#313 id=313 data-nosnippet>313</a>
<a href=#314 id=314 data-nosnippet>314</a> <span class="kw">fn </span>try_from(index: u64) -&gt; <span class="prelude-ty">Result</span>&lt;SmallIndex, SmallIndexError&gt; {
<a href=#315 id=315 data-nosnippet>315</a> <span class="kw">if </span>index &gt; SmallIndex::MAX.as_u64() {
<a href=#316 id=316 data-nosnippet>316</a> <span class="kw">return </span><span class="prelude-val">Err</span>(SmallIndexError { attempted: index });
<a href=#317 id=317 data-nosnippet>317</a> }
<a href=#318 id=318 data-nosnippet>318</a> <span class="prelude-val">Ok</span>(SmallIndex::new_unchecked(index.as_usize()))
<a href=#319 id=319 data-nosnippet>319</a> }
<a href=#320 id=320 data-nosnippet>320</a>}
<a href=#321 id=321 data-nosnippet>321</a>
<a href=#322 id=322 data-nosnippet>322</a><span class="kw">impl </span>TryFrom&lt;usize&gt; <span class="kw">for </span>SmallIndex {
<a href=#323 id=323 data-nosnippet>323</a> <span class="kw">type </span>Error = SmallIndexError;
<a href=#324 id=324 data-nosnippet>324</a>
<a href=#325 id=325 data-nosnippet>325</a> <span class="kw">fn </span>try_from(index: usize) -&gt; <span class="prelude-ty">Result</span>&lt;SmallIndex, SmallIndexError&gt; {
<a href=#326 id=326 data-nosnippet>326</a> <span class="kw">if </span>index &gt; SmallIndex::MAX.as_usize() {
<a href=#327 id=327 data-nosnippet>327</a> <span class="kw">return </span><span class="prelude-val">Err</span>(SmallIndexError { attempted: index.as_u64() });
<a href=#328 id=328 data-nosnippet>328</a> }
<a href=#329 id=329 data-nosnippet>329</a> <span class="prelude-val">Ok</span>(SmallIndex::new_unchecked(index))
<a href=#330 id=330 data-nosnippet>330</a> }
<a href=#331 id=331 data-nosnippet>331</a>}
<a href=#332 id=332 data-nosnippet>332</a>
<a href=#333 id=333 data-nosnippet>333</a><span class="doccomment">/// This error occurs when a small index could not be constructed.
<a href=#334 id=334 data-nosnippet>334</a>///
<a href=#335 id=335 data-nosnippet>335</a>/// This occurs when given an integer exceeding the maximum small index value.
<a href=#336 id=336 data-nosnippet>336</a>///
<a href=#337 id=337 data-nosnippet>337</a>/// When the `std` feature is enabled, this implements the `Error` trait.
<a href=#338 id=338 data-nosnippet>338</a></span><span class="attr">#[derive(Clone, Debug, Eq, PartialEq)]
<a href=#339 id=339 data-nosnippet>339</a></span><span class="kw">pub struct </span>SmallIndexError {
<a href=#340 id=340 data-nosnippet>340</a> attempted: u64,
<a href=#341 id=341 data-nosnippet>341</a>}
<a href=#342 id=342 data-nosnippet>342</a>
<a href=#343 id=343 data-nosnippet>343</a><span class="kw">impl </span>SmallIndexError {
<a href=#344 id=344 data-nosnippet>344</a> <span class="doccomment">/// Returns the value that could not be converted to a small index.
<a href=#345 id=345 data-nosnippet>345</a> </span><span class="kw">pub fn </span>attempted(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; u64 {
<a href=#346 id=346 data-nosnippet>346</a> <span class="self">self</span>.attempted
<a href=#347 id=347 data-nosnippet>347</a> }
<a href=#348 id=348 data-nosnippet>348</a>}
<a href=#349 id=349 data-nosnippet>349</a>
<a href=#350 id=350 data-nosnippet>350</a><span class="attr">#[cfg(feature = <span class="string">"std"</span>)]
<a href=#351 id=351 data-nosnippet>351</a></span><span class="kw">impl </span>std::error::Error <span class="kw">for </span>SmallIndexError {}
<a href=#352 id=352 data-nosnippet>352</a>
<a href=#353 id=353 data-nosnippet>353</a><span class="kw">impl </span>core::fmt::Display <span class="kw">for </span>SmallIndexError {
<a href=#354 id=354 data-nosnippet>354</a> <span class="kw">fn </span>fmt(<span class="kw-2">&amp;</span><span class="self">self</span>, f: <span class="kw-2">&amp;mut </span>core::fmt::Formatter) -&gt; core::fmt::Result {
<a href=#355 id=355 data-nosnippet>355</a> <span class="macro">write!</span>(
<a href=#356 id=356 data-nosnippet>356</a> f,
<a href=#357 id=357 data-nosnippet>357</a> <span class="string">"failed to create small index from {:?}, which exceeds {:?}"</span>,
<a href=#358 id=358 data-nosnippet>358</a> <span class="self">self</span>.attempted(),
<a href=#359 id=359 data-nosnippet>359</a> SmallIndex::MAX,
<a href=#360 id=360 data-nosnippet>360</a> )
<a href=#361 id=361 data-nosnippet>361</a> }
<a href=#362 id=362 data-nosnippet>362</a>}
<a href=#363 id=363 data-nosnippet>363</a>
<a href=#364 id=364 data-nosnippet>364</a><span class="attr">#[derive(Clone, Debug)]
<a href=#365 id=365 data-nosnippet>365</a></span><span class="kw">pub</span>(<span class="kw">crate</span>) <span class="kw">struct </span>SmallIndexIter {
<a href=#366 id=366 data-nosnippet>366</a> rng: core::ops::Range&lt;usize&gt;,
<a href=#367 id=367 data-nosnippet>367</a>}
<a href=#368 id=368 data-nosnippet>368</a>
<a href=#369 id=369 data-nosnippet>369</a><span class="kw">impl </span>Iterator <span class="kw">for </span>SmallIndexIter {
<a href=#370 id=370 data-nosnippet>370</a> <span class="kw">type </span>Item = SmallIndex;
<a href=#371 id=371 data-nosnippet>371</a>
<a href=#372 id=372 data-nosnippet>372</a> <span class="kw">fn </span>next(<span class="kw-2">&amp;mut </span><span class="self">self</span>) -&gt; <span class="prelude-ty">Option</span>&lt;SmallIndex&gt; {
<a href=#373 id=373 data-nosnippet>373</a> <span class="kw">if </span><span class="self">self</span>.rng.start &gt;= <span class="self">self</span>.rng.end {
<a href=#374 id=374 data-nosnippet>374</a> <span class="kw">return </span><span class="prelude-val">None</span>;
<a href=#375 id=375 data-nosnippet>375</a> }
<a href=#376 id=376 data-nosnippet>376</a> <span class="kw">let </span>next_id = <span class="self">self</span>.rng.start + <span class="number">1</span>;
<a href=#377 id=377 data-nosnippet>377</a> <span class="kw">let </span>id = core::mem::replace(<span class="kw-2">&amp;mut </span><span class="self">self</span>.rng.start, next_id);
<a href=#378 id=378 data-nosnippet>378</a> <span class="comment">// new_unchecked is OK since we asserted that the number of
<a href=#379 id=379 data-nosnippet>379</a> // elements in this iterator will fit in an ID at construction.
<a href=#380 id=380 data-nosnippet>380</a> </span><span class="prelude-val">Some</span>(SmallIndex::new_unchecked(id))
<a href=#381 id=381 data-nosnippet>381</a> }
<a href=#382 id=382 data-nosnippet>382</a>}
<a href=#383 id=383 data-nosnippet>383</a>
<a href=#384 id=384 data-nosnippet>384</a><span class="macro">macro_rules!</span> index_type_impls {
<a href=#385 id=385 data-nosnippet>385</a> (<span class="macro-nonterminal">$name</span>:ident, <span class="macro-nonterminal">$err</span>:ident, <span class="macro-nonterminal">$iter</span>:ident, <span class="macro-nonterminal">$withiter</span>:ident) =&gt; {
<a href=#386 id=386 data-nosnippet>386</a> <span class="kw">impl </span><span class="macro-nonterminal">$name </span>{
<a href=#387 id=387 data-nosnippet>387</a> <span class="doccomment">/// The maximum value.
<a href=#388 id=388 data-nosnippet>388</a> </span><span class="kw">pub const </span>MAX: <span class="macro-nonterminal">$name </span>= <span class="macro-nonterminal">$name</span>(SmallIndex::MAX);
<a href=#389 id=389 data-nosnippet>389</a>
<a href=#390 id=390 data-nosnippet>390</a> <span class="doccomment">/// The total number of values that can be represented.
<a href=#391 id=391 data-nosnippet>391</a> </span><span class="kw">pub const </span>LIMIT: usize = SmallIndex::LIMIT;
<a href=#392 id=392 data-nosnippet>392</a>
<a href=#393 id=393 data-nosnippet>393</a> <span class="doccomment">/// The zero value.
<a href=#394 id=394 data-nosnippet>394</a> </span><span class="kw">pub const </span>ZERO: <span class="macro-nonterminal">$name </span>= <span class="macro-nonterminal">$name</span>(SmallIndex::ZERO);
<a href=#395 id=395 data-nosnippet>395</a>
<a href=#396 id=396 data-nosnippet>396</a> <span class="doccomment">/// The number of bytes that a single value uses in memory.
<a href=#397 id=397 data-nosnippet>397</a> </span><span class="kw">pub const </span>SIZE: usize = SmallIndex::SIZE;
<a href=#398 id=398 data-nosnippet>398</a>
<a href=#399 id=399 data-nosnippet>399</a> <span class="doccomment">/// Create a new value that is represented by a "small index."
<a href=#400 id=400 data-nosnippet>400</a> ///
<a href=#401 id=401 data-nosnippet>401</a> /// If the given index exceeds the maximum allowed value, then this
<a href=#402 id=402 data-nosnippet>402</a> /// returns an error.
<a href=#403 id=403 data-nosnippet>403</a> </span><span class="attr">#[inline]
<a href=#404 id=404 data-nosnippet>404</a> </span><span class="kw">pub fn </span>new(value: usize) -&gt; <span class="prelude-ty">Result</span>&lt;<span class="macro-nonterminal">$name</span>, <span class="macro-nonterminal">$err</span>&gt; {
<a href=#405 id=405 data-nosnippet>405</a> SmallIndex::new(value).map(<span class="macro-nonterminal">$name</span>).map_err(<span class="macro-nonterminal">$err</span>)
<a href=#406 id=406 data-nosnippet>406</a> }
<a href=#407 id=407 data-nosnippet>407</a>
<a href=#408 id=408 data-nosnippet>408</a> <span class="doccomment">/// Create a new value without checking whether the given argument
<a href=#409 id=409 data-nosnippet>409</a> /// exceeds the maximum.
<a href=#410 id=410 data-nosnippet>410</a> ///
<a href=#411 id=411 data-nosnippet>411</a> /// Using this routine with an invalid value will result in
<a href=#412 id=412 data-nosnippet>412</a> /// unspecified behavior, but *not* undefined behavior. In
<a href=#413 id=413 data-nosnippet>413</a> /// particular, an invalid ID value is likely to cause panics or
<a href=#414 id=414 data-nosnippet>414</a> /// possibly even silent logical errors.
<a href=#415 id=415 data-nosnippet>415</a> ///
<a href=#416 id=416 data-nosnippet>416</a> /// Callers must never rely on this type to be within a certain
<a href=#417 id=417 data-nosnippet>417</a> /// range for memory safety.
<a href=#418 id=418 data-nosnippet>418</a> </span><span class="attr">#[inline]
<a href=#419 id=419 data-nosnippet>419</a> </span><span class="kw">pub const fn </span>new_unchecked(value: usize) -&gt; <span class="macro-nonterminal">$name </span>{
<a href=#420 id=420 data-nosnippet>420</a> <span class="macro-nonterminal">$name</span>(SmallIndex::new_unchecked(value))
<a href=#421 id=421 data-nosnippet>421</a> }
<a href=#422 id=422 data-nosnippet>422</a>
<a href=#423 id=423 data-nosnippet>423</a> <span class="doccomment">/// Create a new value from a `u32` without checking whether the
<a href=#424 id=424 data-nosnippet>424</a> /// given value exceeds the maximum.
<a href=#425 id=425 data-nosnippet>425</a> ///
<a href=#426 id=426 data-nosnippet>426</a> /// Using this routine with an invalid value will result in
<a href=#427 id=427 data-nosnippet>427</a> /// unspecified behavior, but *not* undefined behavior. In
<a href=#428 id=428 data-nosnippet>428</a> /// particular, an invalid ID value is likely to cause panics or
<a href=#429 id=429 data-nosnippet>429</a> /// possibly even silent logical errors.
<a href=#430 id=430 data-nosnippet>430</a> ///
<a href=#431 id=431 data-nosnippet>431</a> /// Callers must never rely on this type to be within a certain
<a href=#432 id=432 data-nosnippet>432</a> /// range for memory safety.
<a href=#433 id=433 data-nosnippet>433</a> </span><span class="attr">#[inline]
<a href=#434 id=434 data-nosnippet>434</a> </span><span class="kw">pub const fn </span>from_u32_unchecked(index: u32) -&gt; <span class="macro-nonterminal">$name </span>{
<a href=#435 id=435 data-nosnippet>435</a> <span class="macro-nonterminal">$name</span>(SmallIndex::from_u32_unchecked(index))
<a href=#436 id=436 data-nosnippet>436</a> }
<a href=#437 id=437 data-nosnippet>437</a>
<a href=#438 id=438 data-nosnippet>438</a> <span class="doccomment">/// Like `new`, but panics if the given value is not valid.
<a href=#439 id=439 data-nosnippet>439</a> </span><span class="attr">#[inline]
<a href=#440 id=440 data-nosnippet>440</a> </span><span class="kw">pub fn </span>must(value: usize) -&gt; <span class="macro-nonterminal">$name </span>{
<a href=#441 id=441 data-nosnippet>441</a> <span class="macro-nonterminal">$name::new</span>(value).expect(<span class="macro">concat!</span>(
<a href=#442 id=442 data-nosnippet>442</a> <span class="string">"invalid "</span>,
<a href=#443 id=443 data-nosnippet>443</a> <span class="macro">stringify!</span>(<span class="macro-nonterminal">$name</span>),
<a href=#444 id=444 data-nosnippet>444</a> <span class="string">" value"
<a href=#445 id=445 data-nosnippet>445</a> </span>))
<a href=#446 id=446 data-nosnippet>446</a> }
<a href=#447 id=447 data-nosnippet>447</a>
<a href=#448 id=448 data-nosnippet>448</a> <span class="doccomment">/// Return the internal value as a `usize`. This is guaranteed to
<a href=#449 id=449 data-nosnippet>449</a> /// never overflow `usize`.
<a href=#450 id=450 data-nosnippet>450</a> </span><span class="attr">#[inline]
<a href=#451 id=451 data-nosnippet>451</a> </span><span class="kw">pub const fn </span>as_usize(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; usize {
<a href=#452 id=452 data-nosnippet>452</a> <span class="self">self</span>.<span class="number">0</span>.as_usize()
<a href=#453 id=453 data-nosnippet>453</a> }
<a href=#454 id=454 data-nosnippet>454</a>
<a href=#455 id=455 data-nosnippet>455</a> <span class="doccomment">/// Return the internal value as a `u64`. This is guaranteed to
<a href=#456 id=456 data-nosnippet>456</a> /// never overflow.
<a href=#457 id=457 data-nosnippet>457</a> </span><span class="attr">#[inline]
<a href=#458 id=458 data-nosnippet>458</a> </span><span class="kw">pub const fn </span>as_u64(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; u64 {
<a href=#459 id=459 data-nosnippet>459</a> <span class="self">self</span>.<span class="number">0</span>.as_u64()
<a href=#460 id=460 data-nosnippet>460</a> }
<a href=#461 id=461 data-nosnippet>461</a>
<a href=#462 id=462 data-nosnippet>462</a> <span class="doccomment">/// Return the internal value as a `u32`. This is guaranteed to
<a href=#463 id=463 data-nosnippet>463</a> /// never overflow `u32`.
<a href=#464 id=464 data-nosnippet>464</a> </span><span class="attr">#[inline]
<a href=#465 id=465 data-nosnippet>465</a> </span><span class="kw">pub const fn </span>as_u32(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; u32 {
<a href=#466 id=466 data-nosnippet>466</a> <span class="self">self</span>.<span class="number">0</span>.as_u32()
<a href=#467 id=467 data-nosnippet>467</a> }
<a href=#468 id=468 data-nosnippet>468</a>
<a href=#469 id=469 data-nosnippet>469</a> <span class="doccomment">/// Return the internal value as a `i32`. This is guaranteed to
<a href=#470 id=470 data-nosnippet>470</a> /// never overflow an `i32`.
<a href=#471 id=471 data-nosnippet>471</a> </span><span class="attr">#[inline]
<a href=#472 id=472 data-nosnippet>472</a> </span><span class="kw">pub const fn </span>as_i32(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; i32 {
<a href=#473 id=473 data-nosnippet>473</a> <span class="self">self</span>.<span class="number">0</span>.as_i32()
<a href=#474 id=474 data-nosnippet>474</a> }
<a href=#475 id=475 data-nosnippet>475</a>
<a href=#476 id=476 data-nosnippet>476</a> <span class="doccomment">/// Returns one more than this value as a usize.
<a href=#477 id=477 data-nosnippet>477</a> ///
<a href=#478 id=478 data-nosnippet>478</a> /// Since values represented by a "small index" have constraints
<a href=#479 id=479 data-nosnippet>479</a> /// on their maximum value, adding `1` to it will always fit in a
<a href=#480 id=480 data-nosnippet>480</a> /// `usize`, `u32` and a `i32`.
<a href=#481 id=481 data-nosnippet>481</a> </span><span class="attr">#[inline]
<a href=#482 id=482 data-nosnippet>482</a> </span><span class="kw">pub fn </span>one_more(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; usize {
<a href=#483 id=483 data-nosnippet>483</a> <span class="self">self</span>.<span class="number">0</span>.one_more()
<a href=#484 id=484 data-nosnippet>484</a> }
<a href=#485 id=485 data-nosnippet>485</a>
<a href=#486 id=486 data-nosnippet>486</a> <span class="doccomment">/// Decode this value from the bytes given using the native endian
<a href=#487 id=487 data-nosnippet>487</a> /// byte order for the current target.
<a href=#488 id=488 data-nosnippet>488</a> ///
<a href=#489 id=489 data-nosnippet>489</a> /// If the decoded integer is not representable as a small index
<a href=#490 id=490 data-nosnippet>490</a> /// for the current target, then this returns an error.
<a href=#491 id=491 data-nosnippet>491</a> </span><span class="attr">#[inline]
<a href=#492 id=492 data-nosnippet>492</a> </span><span class="kw">pub fn </span>from_ne_bytes(bytes: [u8; <span class="number">4</span>]) -&gt; <span class="prelude-ty">Result</span>&lt;<span class="macro-nonterminal">$name</span>, <span class="macro-nonterminal">$err</span>&gt; {
<a href=#493 id=493 data-nosnippet>493</a> SmallIndex::from_ne_bytes(bytes).map(<span class="macro-nonterminal">$name</span>).map_err(<span class="macro-nonterminal">$err</span>)
<a href=#494 id=494 data-nosnippet>494</a> }
<a href=#495 id=495 data-nosnippet>495</a>
<a href=#496 id=496 data-nosnippet>496</a> <span class="doccomment">/// Decode this value from the bytes given using the native endian
<a href=#497 id=497 data-nosnippet>497</a> /// byte order for the current target.
<a href=#498 id=498 data-nosnippet>498</a> ///
<a href=#499 id=499 data-nosnippet>499</a> /// This is analogous to `new_unchecked` in that is does not check
<a href=#500 id=500 data-nosnippet>500</a> /// whether the decoded integer is representable as a small index.
<a href=#501 id=501 data-nosnippet>501</a> </span><span class="attr">#[inline]
<a href=#502 id=502 data-nosnippet>502</a> </span><span class="kw">pub fn </span>from_ne_bytes_unchecked(bytes: [u8; <span class="number">4</span>]) -&gt; <span class="macro-nonterminal">$name </span>{
<a href=#503 id=503 data-nosnippet>503</a> <span class="macro-nonterminal">$name</span>(SmallIndex::from_ne_bytes_unchecked(bytes))
<a href=#504 id=504 data-nosnippet>504</a> }
<a href=#505 id=505 data-nosnippet>505</a>
<a href=#506 id=506 data-nosnippet>506</a> <span class="doccomment">/// Return the underlying integer as raw bytes in native endian
<a href=#507 id=507 data-nosnippet>507</a> /// format.
<a href=#508 id=508 data-nosnippet>508</a> </span><span class="attr">#[inline]
<a href=#509 id=509 data-nosnippet>509</a> </span><span class="kw">pub fn </span>to_ne_bytes(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; [u8; <span class="number">4</span>] {
<a href=#510 id=510 data-nosnippet>510</a> <span class="self">self</span>.<span class="number">0</span>.to_ne_bytes()
<a href=#511 id=511 data-nosnippet>511</a> }
<a href=#512 id=512 data-nosnippet>512</a>
<a href=#513 id=513 data-nosnippet>513</a> <span class="doccomment">/// Returns an iterator over all values from 0 up to and not
<a href=#514 id=514 data-nosnippet>514</a> /// including the given length.
<a href=#515 id=515 data-nosnippet>515</a> ///
<a href=#516 id=516 data-nosnippet>516</a> /// If the given length exceeds this type's limit, then this
<a href=#517 id=517 data-nosnippet>517</a> /// panics.
<a href=#518 id=518 data-nosnippet>518</a> </span><span class="kw">pub</span>(<span class="kw">crate</span>) <span class="kw">fn </span>iter(len: usize) -&gt; <span class="macro-nonterminal">$iter </span>{
<a href=#519 id=519 data-nosnippet>519</a> <span class="macro-nonterminal">$iter::new</span>(len)
<a href=#520 id=520 data-nosnippet>520</a> }
<a href=#521 id=521 data-nosnippet>521</a> }
<a href=#522 id=522 data-nosnippet>522</a>
<a href=#523 id=523 data-nosnippet>523</a> <span class="comment">// We write our own Debug impl so that we get things like PatternID(5)
<a href=#524 id=524 data-nosnippet>524</a> // instead of PatternID(SmallIndex(5)).
<a href=#525 id=525 data-nosnippet>525</a> </span><span class="kw">impl </span>core::fmt::Debug <span class="kw">for </span><span class="macro-nonterminal">$name </span>{
<a href=#526 id=526 data-nosnippet>526</a> <span class="kw">fn </span>fmt(<span class="kw-2">&amp;</span><span class="self">self</span>, f: <span class="kw-2">&amp;mut </span>core::fmt::Formatter) -&gt; core::fmt::Result {
<a href=#527 id=527 data-nosnippet>527</a> f.debug_tuple(<span class="macro">stringify!</span>(<span class="macro-nonterminal">$name</span>)).field(<span class="kw-2">&amp;</span><span class="self">self</span>.as_u32()).finish()
<a href=#528 id=528 data-nosnippet>528</a> }
<a href=#529 id=529 data-nosnippet>529</a> }
<a href=#530 id=530 data-nosnippet>530</a>
<a href=#531 id=531 data-nosnippet>531</a> <span class="kw">impl</span>&lt;T&gt; core::ops::Index&lt;<span class="macro-nonterminal">$name</span>&gt; <span class="kw">for </span>[T] {
<a href=#532 id=532 data-nosnippet>532</a> <span class="kw">type </span>Output = T;
<a href=#533 id=533 data-nosnippet>533</a>
<a href=#534 id=534 data-nosnippet>534</a> <span class="attr">#[inline]
<a href=#535 id=535 data-nosnippet>535</a> </span><span class="kw">fn </span>index(<span class="kw-2">&amp;</span><span class="self">self</span>, index: <span class="macro-nonterminal">$name</span>) -&gt; <span class="kw-2">&amp;</span>T {
<a href=#536 id=536 data-nosnippet>536</a> <span class="kw-2">&amp;</span><span class="self">self</span>[index.as_usize()]
<a href=#537 id=537 data-nosnippet>537</a> }
<a href=#538 id=538 data-nosnippet>538</a> }
<a href=#539 id=539 data-nosnippet>539</a>
<a href=#540 id=540 data-nosnippet>540</a> <span class="kw">impl</span>&lt;T&gt; core::ops::IndexMut&lt;<span class="macro-nonterminal">$name</span>&gt; <span class="kw">for </span>[T] {
<a href=#541 id=541 data-nosnippet>541</a> <span class="attr">#[inline]
<a href=#542 id=542 data-nosnippet>542</a> </span><span class="kw">fn </span>index_mut(<span class="kw-2">&amp;mut </span><span class="self">self</span>, index: <span class="macro-nonterminal">$name</span>) -&gt; <span class="kw-2">&amp;mut </span>T {
<a href=#543 id=543 data-nosnippet>543</a> <span class="kw-2">&amp;mut </span><span class="self">self</span>[index.as_usize()]
<a href=#544 id=544 data-nosnippet>544</a> }
<a href=#545 id=545 data-nosnippet>545</a> }
<a href=#546 id=546 data-nosnippet>546</a>
<a href=#547 id=547 data-nosnippet>547</a> <span class="kw">impl</span>&lt;T&gt; core::ops::Index&lt;<span class="macro-nonterminal">$name</span>&gt; <span class="kw">for </span>Vec&lt;T&gt; {
<a href=#548 id=548 data-nosnippet>548</a> <span class="kw">type </span>Output = T;
<a href=#549 id=549 data-nosnippet>549</a>
<a href=#550 id=550 data-nosnippet>550</a> <span class="attr">#[inline]
<a href=#551 id=551 data-nosnippet>551</a> </span><span class="kw">fn </span>index(<span class="kw-2">&amp;</span><span class="self">self</span>, index: <span class="macro-nonterminal">$name</span>) -&gt; <span class="kw-2">&amp;</span>T {
<a href=#552 id=552 data-nosnippet>552</a> <span class="kw-2">&amp;</span><span class="self">self</span>[index.as_usize()]
<a href=#553 id=553 data-nosnippet>553</a> }
<a href=#554 id=554 data-nosnippet>554</a> }
<a href=#555 id=555 data-nosnippet>555</a>
<a href=#556 id=556 data-nosnippet>556</a> <span class="kw">impl</span>&lt;T&gt; core::ops::IndexMut&lt;<span class="macro-nonterminal">$name</span>&gt; <span class="kw">for </span>Vec&lt;T&gt; {
<a href=#557 id=557 data-nosnippet>557</a> <span class="attr">#[inline]
<a href=#558 id=558 data-nosnippet>558</a> </span><span class="kw">fn </span>index_mut(<span class="kw-2">&amp;mut </span><span class="self">self</span>, index: <span class="macro-nonterminal">$name</span>) -&gt; <span class="kw-2">&amp;mut </span>T {
<a href=#559 id=559 data-nosnippet>559</a> <span class="kw-2">&amp;mut </span><span class="self">self</span>[index.as_usize()]
<a href=#560 id=560 data-nosnippet>560</a> }
<a href=#561 id=561 data-nosnippet>561</a> }
<a href=#562 id=562 data-nosnippet>562</a>
<a href=#563 id=563 data-nosnippet>563</a> <span class="kw">impl </span>From&lt;SmallIndex&gt; <span class="kw">for </span><span class="macro-nonterminal">$name </span>{
<a href=#564 id=564 data-nosnippet>564</a> <span class="kw">fn </span>from(index: SmallIndex) -&gt; <span class="macro-nonterminal">$name </span>{
<a href=#565 id=565 data-nosnippet>565</a> <span class="macro-nonterminal">$name</span>(index)
<a href=#566 id=566 data-nosnippet>566</a> }
<a href=#567 id=567 data-nosnippet>567</a> }
<a href=#568 id=568 data-nosnippet>568</a>
<a href=#569 id=569 data-nosnippet>569</a> <span class="kw">impl </span>From&lt;u8&gt; <span class="kw">for </span><span class="macro-nonterminal">$name </span>{
<a href=#570 id=570 data-nosnippet>570</a> <span class="kw">fn </span>from(value: u8) -&gt; <span class="macro-nonterminal">$name </span>{
<a href=#571 id=571 data-nosnippet>571</a> <span class="macro-nonterminal">$name</span>(SmallIndex::from(value))
<a href=#572 id=572 data-nosnippet>572</a> }
<a href=#573 id=573 data-nosnippet>573</a> }
<a href=#574 id=574 data-nosnippet>574</a>
<a href=#575 id=575 data-nosnippet>575</a> <span class="kw">impl </span>TryFrom&lt;u16&gt; <span class="kw">for </span><span class="macro-nonterminal">$name </span>{
<a href=#576 id=576 data-nosnippet>576</a> <span class="kw">type </span>Error = <span class="macro-nonterminal">$err</span>;
<a href=#577 id=577 data-nosnippet>577</a>
<a href=#578 id=578 data-nosnippet>578</a> <span class="kw">fn </span>try_from(value: u16) -&gt; <span class="prelude-ty">Result</span>&lt;<span class="macro-nonterminal">$name</span>, <span class="macro-nonterminal">$err</span>&gt; {
<a href=#579 id=579 data-nosnippet>579</a> SmallIndex::try_from(value).map(<span class="macro-nonterminal">$name</span>).map_err(<span class="macro-nonterminal">$err</span>)
<a href=#580 id=580 data-nosnippet>580</a> }
<a href=#581 id=581 data-nosnippet>581</a> }
<a href=#582 id=582 data-nosnippet>582</a>
<a href=#583 id=583 data-nosnippet>583</a> <span class="kw">impl </span>TryFrom&lt;u32&gt; <span class="kw">for </span><span class="macro-nonterminal">$name </span>{
<a href=#584 id=584 data-nosnippet>584</a> <span class="kw">type </span>Error = <span class="macro-nonterminal">$err</span>;
<a href=#585 id=585 data-nosnippet>585</a>
<a href=#586 id=586 data-nosnippet>586</a> <span class="kw">fn </span>try_from(value: u32) -&gt; <span class="prelude-ty">Result</span>&lt;<span class="macro-nonterminal">$name</span>, <span class="macro-nonterminal">$err</span>&gt; {
<a href=#587 id=587 data-nosnippet>587</a> SmallIndex::try_from(value).map(<span class="macro-nonterminal">$name</span>).map_err(<span class="macro-nonterminal">$err</span>)
<a href=#588 id=588 data-nosnippet>588</a> }
<a href=#589 id=589 data-nosnippet>589</a> }
<a href=#590 id=590 data-nosnippet>590</a>
<a href=#591 id=591 data-nosnippet>591</a> <span class="kw">impl </span>TryFrom&lt;u64&gt; <span class="kw">for </span><span class="macro-nonterminal">$name </span>{
<a href=#592 id=592 data-nosnippet>592</a> <span class="kw">type </span>Error = <span class="macro-nonterminal">$err</span>;
<a href=#593 id=593 data-nosnippet>593</a>
<a href=#594 id=594 data-nosnippet>594</a> <span class="kw">fn </span>try_from(value: u64) -&gt; <span class="prelude-ty">Result</span>&lt;<span class="macro-nonterminal">$name</span>, <span class="macro-nonterminal">$err</span>&gt; {
<a href=#595 id=595 data-nosnippet>595</a> SmallIndex::try_from(value).map(<span class="macro-nonterminal">$name</span>).map_err(<span class="macro-nonterminal">$err</span>)
<a href=#596 id=596 data-nosnippet>596</a> }
<a href=#597 id=597 data-nosnippet>597</a> }
<a href=#598 id=598 data-nosnippet>598</a>
<a href=#599 id=599 data-nosnippet>599</a> <span class="kw">impl </span>TryFrom&lt;usize&gt; <span class="kw">for </span><span class="macro-nonterminal">$name </span>{
<a href=#600 id=600 data-nosnippet>600</a> <span class="kw">type </span>Error = <span class="macro-nonterminal">$err</span>;
<a href=#601 id=601 data-nosnippet>601</a>
<a href=#602 id=602 data-nosnippet>602</a> <span class="kw">fn </span>try_from(value: usize) -&gt; <span class="prelude-ty">Result</span>&lt;<span class="macro-nonterminal">$name</span>, <span class="macro-nonterminal">$err</span>&gt; {
<a href=#603 id=603 data-nosnippet>603</a> SmallIndex::try_from(value).map(<span class="macro-nonterminal">$name</span>).map_err(<span class="macro-nonterminal">$err</span>)
<a href=#604 id=604 data-nosnippet>604</a> }
<a href=#605 id=605 data-nosnippet>605</a> }
<a href=#606 id=606 data-nosnippet>606</a>
<a href=#607 id=607 data-nosnippet>607</a> <span class="doccomment">/// This error occurs when an ID could not be constructed.
<a href=#608 id=608 data-nosnippet>608</a> ///
<a href=#609 id=609 data-nosnippet>609</a> /// This occurs when given an integer exceeding the maximum allowed
<a href=#610 id=610 data-nosnippet>610</a> /// value.
<a href=#611 id=611 data-nosnippet>611</a> ///
<a href=#612 id=612 data-nosnippet>612</a> /// When the `std` feature is enabled, this implements the `Error`
<a href=#613 id=613 data-nosnippet>613</a> /// trait.
<a href=#614 id=614 data-nosnippet>614</a> </span><span class="attr">#[derive(Clone, Debug, Eq, PartialEq)]
<a href=#615 id=615 data-nosnippet>615</a> </span><span class="kw">pub struct </span><span class="macro-nonterminal">$err</span>(SmallIndexError);
<a href=#616 id=616 data-nosnippet>616</a>
<a href=#617 id=617 data-nosnippet>617</a> <span class="kw">impl </span><span class="macro-nonterminal">$err </span>{
<a href=#618 id=618 data-nosnippet>618</a> <span class="doccomment">/// Returns the value that could not be converted to an ID.
<a href=#619 id=619 data-nosnippet>619</a> </span><span class="kw">pub fn </span>attempted(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; u64 {
<a href=#620 id=620 data-nosnippet>620</a> <span class="self">self</span>.<span class="number">0</span>.attempted()
<a href=#621 id=621 data-nosnippet>621</a> }
<a href=#622 id=622 data-nosnippet>622</a> }
<a href=#623 id=623 data-nosnippet>623</a>
<a href=#624 id=624 data-nosnippet>624</a> <span class="attr">#[cfg(feature = <span class="string">"std"</span>)]
<a href=#625 id=625 data-nosnippet>625</a> </span><span class="kw">impl </span>std::error::Error <span class="kw">for </span><span class="macro-nonterminal">$err </span>{}
<a href=#626 id=626 data-nosnippet>626</a>
<a href=#627 id=627 data-nosnippet>627</a> <span class="kw">impl </span>core::fmt::Display <span class="kw">for </span><span class="macro-nonterminal">$err </span>{
<a href=#628 id=628 data-nosnippet>628</a> <span class="kw">fn </span>fmt(<span class="kw-2">&amp;</span><span class="self">self</span>, f: <span class="kw-2">&amp;mut </span>core::fmt::Formatter) -&gt; core::fmt::Result {
<a href=#629 id=629 data-nosnippet>629</a> <span class="macro">write!</span>(
<a href=#630 id=630 data-nosnippet>630</a> f,
<a href=#631 id=631 data-nosnippet>631</a> <span class="string">"failed to create {} from {:?}, which exceeds {:?}"</span>,
<a href=#632 id=632 data-nosnippet>632</a> <span class="macro">stringify!</span>(<span class="macro-nonterminal">$name</span>),
<a href=#633 id=633 data-nosnippet>633</a> <span class="self">self</span>.attempted(),
<a href=#634 id=634 data-nosnippet>634</a> <span class="macro-nonterminal">$name::MAX</span>,
<a href=#635 id=635 data-nosnippet>635</a> )
<a href=#636 id=636 data-nosnippet>636</a> }
<a href=#637 id=637 data-nosnippet>637</a> }
<a href=#638 id=638 data-nosnippet>638</a>
<a href=#639 id=639 data-nosnippet>639</a> <span class="attr">#[derive(Clone, Debug)]
<a href=#640 id=640 data-nosnippet>640</a> </span><span class="kw">pub</span>(<span class="kw">crate</span>) <span class="kw">struct </span><span class="macro-nonterminal">$iter</span>(SmallIndexIter);
<a href=#641 id=641 data-nosnippet>641</a>
<a href=#642 id=642 data-nosnippet>642</a> <span class="kw">impl </span><span class="macro-nonterminal">$iter </span>{
<a href=#643 id=643 data-nosnippet>643</a> <span class="kw">fn </span>new(len: usize) -&gt; <span class="macro-nonterminal">$iter </span>{
<a href=#644 id=644 data-nosnippet>644</a> <span class="macro">assert!</span>(
<a href=#645 id=645 data-nosnippet>645</a> len &lt;= <span class="macro-nonterminal">$name::LIMIT</span>,
<a href=#646 id=646 data-nosnippet>646</a> <span class="string">"cannot create iterator for {} when number of \
<a href=#647 id=647 data-nosnippet>647</a> elements exceed {:?}"</span>,
<a href=#648 id=648 data-nosnippet>648</a> <span class="macro">stringify!</span>(<span class="macro-nonterminal">$name</span>),
<a href=#649 id=649 data-nosnippet>649</a> <span class="macro-nonterminal">$name::LIMIT</span>,
<a href=#650 id=650 data-nosnippet>650</a> );
<a href=#651 id=651 data-nosnippet>651</a> <span class="macro-nonterminal">$iter</span>(SmallIndexIter { rng: <span class="number">0</span>..len })
<a href=#652 id=652 data-nosnippet>652</a> }
<a href=#653 id=653 data-nosnippet>653</a> }
<a href=#654 id=654 data-nosnippet>654</a>
<a href=#655 id=655 data-nosnippet>655</a> <span class="kw">impl </span>Iterator <span class="kw">for </span><span class="macro-nonterminal">$iter </span>{
<a href=#656 id=656 data-nosnippet>656</a> <span class="kw">type </span>Item = <span class="macro-nonterminal">$name</span>;
<a href=#657 id=657 data-nosnippet>657</a>
<a href=#658 id=658 data-nosnippet>658</a> <span class="kw">fn </span>next(<span class="kw-2">&amp;mut </span><span class="self">self</span>) -&gt; <span class="prelude-ty">Option</span>&lt;<span class="macro-nonterminal">$name</span>&gt; {
<a href=#659 id=659 data-nosnippet>659</a> <span class="self">self</span>.<span class="number">0</span>.next().map(<span class="macro-nonterminal">$name</span>)
<a href=#660 id=660 data-nosnippet>660</a> }
<a href=#661 id=661 data-nosnippet>661</a> }
<a href=#662 id=662 data-nosnippet>662</a>
<a href=#663 id=663 data-nosnippet>663</a> <span class="doccomment">/// An iterator adapter that is like std::iter::Enumerate, but attaches
<a href=#664 id=664 data-nosnippet>664</a> /// small index values instead. It requires `ExactSizeIterator`. At
<a href=#665 id=665 data-nosnippet>665</a> /// construction, it ensures that the index of each element in the
<a href=#666 id=666 data-nosnippet>666</a> /// iterator is representable in the corresponding small index type.
<a href=#667 id=667 data-nosnippet>667</a> </span><span class="attr">#[derive(Clone, Debug)]
<a href=#668 id=668 data-nosnippet>668</a> </span><span class="kw">pub</span>(<span class="kw">crate</span>) <span class="kw">struct </span><span class="macro-nonterminal">$withiter</span>&lt;I&gt; {
<a href=#669 id=669 data-nosnippet>669</a> it: I,
<a href=#670 id=670 data-nosnippet>670</a> ids: <span class="macro-nonterminal">$iter</span>,
<a href=#671 id=671 data-nosnippet>671</a> }
<a href=#672 id=672 data-nosnippet>672</a>
<a href=#673 id=673 data-nosnippet>673</a> <span class="kw">impl</span>&lt;I: Iterator + ExactSizeIterator&gt; <span class="macro-nonterminal">$withiter</span>&lt;I&gt; {
<a href=#674 id=674 data-nosnippet>674</a> <span class="kw">fn </span>new(it: I) -&gt; <span class="macro-nonterminal">$withiter</span>&lt;I&gt; {
<a href=#675 id=675 data-nosnippet>675</a> <span class="kw">let </span>ids = <span class="macro-nonterminal">$name::iter</span>(it.len());
<a href=#676 id=676 data-nosnippet>676</a> <span class="macro-nonterminal">$withiter </span>{ it, ids }
<a href=#677 id=677 data-nosnippet>677</a> }
<a href=#678 id=678 data-nosnippet>678</a> }
<a href=#679 id=679 data-nosnippet>679</a>
<a href=#680 id=680 data-nosnippet>680</a> <span class="kw">impl</span>&lt;I: Iterator + ExactSizeIterator&gt; Iterator <span class="kw">for </span><span class="macro-nonterminal">$withiter</span>&lt;I&gt; {
<a href=#681 id=681 data-nosnippet>681</a> <span class="kw">type </span>Item = (<span class="macro-nonterminal">$name</span>, I::Item);
<a href=#682 id=682 data-nosnippet>682</a>
<a href=#683 id=683 data-nosnippet>683</a> <span class="kw">fn </span>next(<span class="kw-2">&amp;mut </span><span class="self">self</span>) -&gt; <span class="prelude-ty">Option</span>&lt;(<span class="macro-nonterminal">$name</span>, I::Item)&gt; {
<a href=#684 id=684 data-nosnippet>684</a> <span class="kw">let </span>item = <span class="self">self</span>.it.next()<span class="question-mark">?</span>;
<a href=#685 id=685 data-nosnippet>685</a> <span class="comment">// Number of elements in this iterator must match, according
<a href=#686 id=686 data-nosnippet>686</a> // to contract of ExactSizeIterator.
<a href=#687 id=687 data-nosnippet>687</a> </span><span class="kw">let </span>id = <span class="self">self</span>.ids.next().unwrap();
<a href=#688 id=688 data-nosnippet>688</a> <span class="prelude-val">Some</span>((id, item))
<a href=#689 id=689 data-nosnippet>689</a> }
<a href=#690 id=690 data-nosnippet>690</a> }
<a href=#691 id=691 data-nosnippet>691</a> };
<a href=#692 id=692 data-nosnippet>692</a>}
<a href=#693 id=693 data-nosnippet>693</a>
<a href=#694 id=694 data-nosnippet>694</a><span class="doccomment">/// The identifier of a pattern in an Aho-Corasick automaton.
<a href=#695 id=695 data-nosnippet>695</a>///
<a href=#696 id=696 data-nosnippet>696</a>/// It is represented by a `u32` even on 64-bit systems in order to conserve
<a href=#697 id=697 data-nosnippet>697</a>/// space. Namely, on all targets, this type guarantees that its value will
<a href=#698 id=698 data-nosnippet>698</a>/// fit in a `u32`, `i32`, `usize` and an `isize`. This means that on 16-bit
<a href=#699 id=699 data-nosnippet>699</a>/// targets, for example, this type's maximum value will never overflow an
<a href=#700 id=700 data-nosnippet>700</a>/// `isize`, which means it will never overflow a `i16` even though its
<a href=#701 id=701 data-nosnippet>701</a>/// internal representation is still a `u32`.
<a href=#702 id=702 data-nosnippet>702</a>///
<a href=#703 id=703 data-nosnippet>703</a>/// # Safety
<a href=#704 id=704 data-nosnippet>704</a>///
<a href=#705 id=705 data-nosnippet>705</a>/// While a `PatternID` is meant to guarantee that its value fits into `usize`
<a href=#706 id=706 data-nosnippet>706</a>/// without using as much space as a `usize` on all targets, callers must
<a href=#707 id=707 data-nosnippet>707</a>/// not rely on this property for safety. Callers may choose to rely on this
<a href=#708 id=708 data-nosnippet>708</a>/// property for correctness however. For example, creating a `StateID` with an
<a href=#709 id=709 data-nosnippet>709</a>/// invalid value can be done in entirely safe code. This may in turn result in
<a href=#710 id=710 data-nosnippet>710</a>/// panics or silent logical errors.
<a href=#711 id=711 data-nosnippet>711</a></span><span class="attr">#[derive(Clone, Copy, Default, Eq, Hash, PartialEq, PartialOrd, Ord)]
<a href=#712 id=712 data-nosnippet>712</a>#[repr(transparent)]
<a href=#713 id=713 data-nosnippet>713</a></span><span class="kw">pub struct </span>PatternID(SmallIndex);
<a href=#714 id=714 data-nosnippet>714</a>
<a href=#715 id=715 data-nosnippet>715</a><span class="doccomment">/// The identifier of a finite automaton state.
<a href=#716 id=716 data-nosnippet>716</a>///
<a href=#717 id=717 data-nosnippet>717</a>/// It is represented by a `u32` even on 64-bit systems in order to conserve
<a href=#718 id=718 data-nosnippet>718</a>/// space. Namely, on all targets, this type guarantees that its value will
<a href=#719 id=719 data-nosnippet>719</a>/// fit in a `u32`, `i32`, `usize` and an `isize`. This means that on 16-bit
<a href=#720 id=720 data-nosnippet>720</a>/// targets, for example, this type's maximum value will never overflow an
<a href=#721 id=721 data-nosnippet>721</a>/// `isize`, which means it will never overflow a `i16` even though its
<a href=#722 id=722 data-nosnippet>722</a>/// internal representation is still a `u32`.
<a href=#723 id=723 data-nosnippet>723</a>///
<a href=#724 id=724 data-nosnippet>724</a>/// # Safety
<a href=#725 id=725 data-nosnippet>725</a>///
<a href=#726 id=726 data-nosnippet>726</a>/// While a `StateID` is meant to guarantee that its value fits into `usize`
<a href=#727 id=727 data-nosnippet>727</a>/// without using as much space as a `usize` on all targets, callers must
<a href=#728 id=728 data-nosnippet>728</a>/// not rely on this property for safety. Callers may choose to rely on this
<a href=#729 id=729 data-nosnippet>729</a>/// property for correctness however. For example, creating a `StateID` with an
<a href=#730 id=730 data-nosnippet>730</a>/// invalid value can be done in entirely safe code. This may in turn result in
<a href=#731 id=731 data-nosnippet>731</a>/// panics or silent logical errors.
<a href=#732 id=732 data-nosnippet>732</a></span><span class="attr">#[derive(Clone, Copy, Default, Eq, Hash, PartialEq, PartialOrd, Ord)]
<a href=#733 id=733 data-nosnippet>733</a>#[repr(transparent)]
<a href=#734 id=734 data-nosnippet>734</a></span><span class="kw">pub struct </span>StateID(SmallIndex);
<a href=#735 id=735 data-nosnippet>735</a>
<a href=#736 id=736 data-nosnippet>736</a><span class="macro">index_type_impls!</span>(PatternID, PatternIDError, PatternIDIter, WithPatternIDIter);
<a href=#737 id=737 data-nosnippet>737</a><span class="macro">index_type_impls!</span>(StateID, StateIDError, StateIDIter, WithStateIDIter);
<a href=#738 id=738 data-nosnippet>738</a>
<a href=#739 id=739 data-nosnippet>739</a><span class="doccomment">/// A utility trait that defines a couple of adapters for making it convenient
<a href=#740 id=740 data-nosnippet>740</a>/// to access indices as "small index" types. We require ExactSizeIterator so
<a href=#741 id=741 data-nosnippet>741</a>/// that iterator construction can do a single check to make sure the index of
<a href=#742 id=742 data-nosnippet>742</a>/// each element is representable by its small index type.
<a href=#743 id=743 data-nosnippet>743</a></span><span class="kw">pub</span>(<span class="kw">crate</span>) <span class="kw">trait </span>IteratorIndexExt: Iterator {
<a href=#744 id=744 data-nosnippet>744</a> <span class="kw">fn </span>with_pattern_ids(<span class="self">self</span>) -&gt; WithPatternIDIter&lt;<span class="self">Self</span>&gt;
<a href=#745 id=745 data-nosnippet>745</a> <span class="kw">where
<a href=#746 id=746 data-nosnippet>746</a> </span><span class="self">Self</span>: Sized + ExactSizeIterator,
<a href=#747 id=747 data-nosnippet>747</a> {
<a href=#748 id=748 data-nosnippet>748</a> WithPatternIDIter::new(<span class="self">self</span>)
<a href=#749 id=749 data-nosnippet>749</a> }
<a href=#750 id=750 data-nosnippet>750</a>
<a href=#751 id=751 data-nosnippet>751</a> <span class="kw">fn </span>with_state_ids(<span class="self">self</span>) -&gt; WithStateIDIter&lt;<span class="self">Self</span>&gt;
<a href=#752 id=752 data-nosnippet>752</a> <span class="kw">where
<a href=#753 id=753 data-nosnippet>753</a> </span><span class="self">Self</span>: Sized + ExactSizeIterator,
<a href=#754 id=754 data-nosnippet>754</a> {
<a href=#755 id=755 data-nosnippet>755</a> WithStateIDIter::new(<span class="self">self</span>)
<a href=#756 id=756 data-nosnippet>756</a> }
<a href=#757 id=757 data-nosnippet>757</a>}
<a href=#758 id=758 data-nosnippet>758</a>
<a href=#759 id=759 data-nosnippet>759</a><span class="kw">impl</span>&lt;I: Iterator&gt; IteratorIndexExt <span class="kw">for </span>I {}
</code></pre></div></section></main></body></html>

View File

@@ -0,0 +1,215 @@
<!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 `/home/newkirk/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/aho-corasick-1.1.4/src/util/remapper.rs`."><title>remapper.rs - source</title><script>if(window.location.protocol!=="file:")document.head.insertAdjacentHTML("beforeend","SourceSerif4-Regular-6b053e98.ttf.woff2,FiraSans-Italic-81dc35de.woff2,FiraSans-Regular-0fe48ade.woff2,FiraSans-MediumItalic-ccf7e434.woff2,FiraSans-Medium-e1aa3f0a.woff2,SourceCodePro-Regular-8badfe75.ttf.woff2,SourceCodePro-Semibold-aa29a496.ttf.woff2".split(",").map(f=>`<link rel="preload" as="font" type="font/woff2"href="../../../static.files/${f}">`).join(""))</script><link rel="stylesheet" href="../../../static.files/normalize-9960930a.css"><link rel="stylesheet" href="../../../static.files/rustdoc-ca0dd0c4.css"><meta name="rustdoc-vars" data-root-path="../../../" data-static-root-path="../../../static.files/" data-current-crate="aho_corasick" data-themes="" data-resource-suffix="" data-rustdoc-version="1.93.1 (01f6ddf75 2026-02-11) (Arch Linux rust 1:1.93.1-1)" data-channel="1.93.1" data-search-js="search-9e2438ea.js" data-stringdex-js="stringdex-a3946164.js" data-settings-js="settings-c38705f0.js" ><script src="../../../static.files/storage-e2aeef58.js"></script><script defer src="../../../static.files/src-script-813739b1.js"></script><script defer src="../../../src-files.js"></script><script defer src="../../../static.files/main-a410ff4d.js"></script><noscript><link rel="stylesheet" href="../../../static.files/noscript-263c88ec.css"></noscript><link rel="alternate icon" type="image/png" href="../../../static.files/favicon-32x32-eab170b8.png"><link rel="icon" type="image/svg+xml" href="../../../static.files/favicon-044be391.svg"></head><body class="rustdoc src"><!--[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="src-sidebar-title"><h2>Files</h2></div></nav><div class="sidebar-resizer" title="Drag to resize sidebar"></div><main><section id="main-content" class="content"><div class="main-heading"><h1><div class="sub-heading">aho_corasick/util/</div>remapper.rs</h1><rustdoc-toolbar></rustdoc-toolbar></div><div class="example-wrap digits-3"><pre class="rust"><code><a href=#1 id=1 data-nosnippet>1</a><span class="kw">use </span>alloc::vec::Vec;
<a href=#2 id=2 data-nosnippet>2</a>
<a href=#3 id=3 data-nosnippet>3</a><span class="kw">use crate</span>::{nfa::noncontiguous, util::primitives::StateID};
<a href=#4 id=4 data-nosnippet>4</a>
<a href=#5 id=5 data-nosnippet>5</a><span class="doccomment">/// Remappable is a tightly coupled abstraction that facilitates remapping
<a href=#6 id=6 data-nosnippet>6</a>/// state identifiers in DFAs.
<a href=#7 id=7 data-nosnippet>7</a>///
<a href=#8 id=8 data-nosnippet>8</a>/// The main idea behind remapping state IDs is that DFAs often need to check
<a href=#9 id=9 data-nosnippet>9</a>/// if a certain state is a "special" state of some kind (like a match state)
<a href=#10 id=10 data-nosnippet>10</a>/// during a search. Since this is extremely perf critical code, we want this
<a href=#11 id=11 data-nosnippet>11</a>/// check to be as fast as possible. Partitioning state IDs into, for example,
<a href=#12 id=12 data-nosnippet>12</a>/// into "non-match" and "match" states means one can tell if a state is a
<a href=#13 id=13 data-nosnippet>13</a>/// match state via a simple comparison of the state ID.
<a href=#14 id=14 data-nosnippet>14</a>///
<a href=#15 id=15 data-nosnippet>15</a>/// The issue is that during the DFA construction process, it's not
<a href=#16 id=16 data-nosnippet>16</a>/// particularly easy to partition the states. Instead, the simplest thing is
<a href=#17 id=17 data-nosnippet>17</a>/// to often just do a pass over all of the states and shuffle them into their
<a href=#18 id=18 data-nosnippet>18</a>/// desired partitionings. To do that, we need a mechanism for swapping states.
<a href=#19 id=19 data-nosnippet>19</a>/// Hence, this abstraction.
<a href=#20 id=20 data-nosnippet>20</a>///
<a href=#21 id=21 data-nosnippet>21</a>/// Normally, for such little code, I would just duplicate it. But this is a
<a href=#22 id=22 data-nosnippet>22</a>/// key optimization and the implementation is a bit subtle. So the abstraction
<a href=#23 id=23 data-nosnippet>23</a>/// is basically a ham-fisted attempt at DRY. The only place we use this is in
<a href=#24 id=24 data-nosnippet>24</a>/// the dense and one-pass DFAs.
<a href=#25 id=25 data-nosnippet>25</a>///
<a href=#26 id=26 data-nosnippet>26</a>/// See also src/dfa/special.rs for a more detailed explanation of how dense
<a href=#27 id=27 data-nosnippet>27</a>/// DFAs are partitioned.
<a href=#28 id=28 data-nosnippet>28</a></span><span class="kw">pub</span>(<span class="kw">crate</span>) <span class="kw">trait </span>Remappable: core::fmt::Debug {
<a href=#29 id=29 data-nosnippet>29</a> <span class="doccomment">/// Return the total number of states.
<a href=#30 id=30 data-nosnippet>30</a> </span><span class="kw">fn </span>state_len(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; usize;
<a href=#31 id=31 data-nosnippet>31</a>
<a href=#32 id=32 data-nosnippet>32</a> <span class="doccomment">/// Swap the states pointed to by the given IDs. The underlying finite
<a href=#33 id=33 data-nosnippet>33</a> /// state machine should be mutated such that all of the transitions in
<a href=#34 id=34 data-nosnippet>34</a> /// `id1` are now in the memory region where the transitions for `id2`
<a href=#35 id=35 data-nosnippet>35</a> /// were, and all of the transitions in `id2` are now in the memory region
<a href=#36 id=36 data-nosnippet>36</a> /// where the transitions for `id1` were.
<a href=#37 id=37 data-nosnippet>37</a> ///
<a href=#38 id=38 data-nosnippet>38</a> /// Essentially, this "moves" `id1` to `id2` and `id2` to `id1`.
<a href=#39 id=39 data-nosnippet>39</a> ///
<a href=#40 id=40 data-nosnippet>40</a> /// It is expected that, after calling this, the underlying state machine
<a href=#41 id=41 data-nosnippet>41</a> /// will be left in an inconsistent state, since any other transitions
<a href=#42 id=42 data-nosnippet>42</a> /// pointing to, e.g., `id1` need to be updated to point to `id2`, since
<a href=#43 id=43 data-nosnippet>43</a> /// that's where `id1` moved to.
<a href=#44 id=44 data-nosnippet>44</a> ///
<a href=#45 id=45 data-nosnippet>45</a> /// In order to "fix" the underlying inconsistent state, a `Remapper`
<a href=#46 id=46 data-nosnippet>46</a> /// should be used to guarantee that `remap` is called at the appropriate
<a href=#47 id=47 data-nosnippet>47</a> /// time.
<a href=#48 id=48 data-nosnippet>48</a> </span><span class="kw">fn </span>swap_states(<span class="kw-2">&amp;mut </span><span class="self">self</span>, id1: StateID, id2: StateID);
<a href=#49 id=49 data-nosnippet>49</a>
<a href=#50 id=50 data-nosnippet>50</a> <span class="doccomment">/// This must remap every single state ID in the underlying value according
<a href=#51 id=51 data-nosnippet>51</a> /// to the function given. For example, in a DFA, this should remap every
<a href=#52 id=52 data-nosnippet>52</a> /// transition and every starting state ID.
<a href=#53 id=53 data-nosnippet>53</a> </span><span class="kw">fn </span>remap(<span class="kw-2">&amp;mut </span><span class="self">self</span>, map: <span class="kw">impl </span>Fn(StateID) -&gt; StateID);
<a href=#54 id=54 data-nosnippet>54</a>}
<a href=#55 id=55 data-nosnippet>55</a>
<a href=#56 id=56 data-nosnippet>56</a><span class="doccomment">/// Remapper is an abstraction the manages the remapping of state IDs in a
<a href=#57 id=57 data-nosnippet>57</a>/// finite state machine. This is useful when one wants to shuffle states into
<a href=#58 id=58 data-nosnippet>58</a>/// different positions in the machine.
<a href=#59 id=59 data-nosnippet>59</a>///
<a href=#60 id=60 data-nosnippet>60</a>/// One of the key complexities this manages is the ability to correctly move
<a href=#61 id=61 data-nosnippet>61</a>/// one state multiple times.
<a href=#62 id=62 data-nosnippet>62</a>///
<a href=#63 id=63 data-nosnippet>63</a>/// Once shuffling is complete, `remap` must be called, which will rewrite
<a href=#64 id=64 data-nosnippet>64</a>/// all pertinent transitions to updated state IDs. Neglecting to call `remap`
<a href=#65 id=65 data-nosnippet>65</a>/// will almost certainly result in a corrupt machine.
<a href=#66 id=66 data-nosnippet>66</a></span><span class="attr">#[derive(Debug)]
<a href=#67 id=67 data-nosnippet>67</a></span><span class="kw">pub</span>(<span class="kw">crate</span>) <span class="kw">struct </span>Remapper {
<a href=#68 id=68 data-nosnippet>68</a> <span class="doccomment">/// A map from the index of a state to its pre-multiplied identifier.
<a href=#69 id=69 data-nosnippet>69</a> ///
<a href=#70 id=70 data-nosnippet>70</a> /// When a state is swapped with another, then their corresponding
<a href=#71 id=71 data-nosnippet>71</a> /// locations in this map are also swapped. Thus, its new position will
<a href=#72 id=72 data-nosnippet>72</a> /// still point to its old pre-multiplied StateID.
<a href=#73 id=73 data-nosnippet>73</a> ///
<a href=#74 id=74 data-nosnippet>74</a> /// While there is a bit more to it, this then allows us to rewrite the
<a href=#75 id=75 data-nosnippet>75</a> /// state IDs in a DFA's transition table in a single pass. This is done
<a href=#76 id=76 data-nosnippet>76</a> /// by iterating over every ID in this map, then iterating over each
<a href=#77 id=77 data-nosnippet>77</a> /// transition for the state at that ID and re-mapping the transition from
<a href=#78 id=78 data-nosnippet>78</a> /// `old_id` to `map[dfa.to_index(old_id)]`. That is, we find the position
<a href=#79 id=79 data-nosnippet>79</a> /// in this map where `old_id` *started*, and set it to where it ended up
<a href=#80 id=80 data-nosnippet>80</a> /// after all swaps have been completed.
<a href=#81 id=81 data-nosnippet>81</a> </span>map: Vec&lt;StateID&gt;,
<a href=#82 id=82 data-nosnippet>82</a> <span class="doccomment">/// A way to map indices to state IDs (and back).
<a href=#83 id=83 data-nosnippet>83</a> </span>idx: IndexMapper,
<a href=#84 id=84 data-nosnippet>84</a>}
<a href=#85 id=85 data-nosnippet>85</a>
<a href=#86 id=86 data-nosnippet>86</a><span class="kw">impl </span>Remapper {
<a href=#87 id=87 data-nosnippet>87</a> <span class="doccomment">/// Create a new remapper from the given remappable implementation. The
<a href=#88 id=88 data-nosnippet>88</a> /// remapper can then be used to swap states. The remappable value given
<a href=#89 id=89 data-nosnippet>89</a> /// here must the same one given to `swap` and `remap`.
<a href=#90 id=90 data-nosnippet>90</a> ///
<a href=#91 id=91 data-nosnippet>91</a> /// The given stride should be the stride of the transition table expressed
<a href=#92 id=92 data-nosnippet>92</a> /// as a power of 2. This stride is used to map between state IDs and state
<a href=#93 id=93 data-nosnippet>93</a> /// indices. If state IDs and state indices are equivalent, then provide
<a href=#94 id=94 data-nosnippet>94</a> /// a `stride2` of `0`, which acts as an identity.
<a href=#95 id=95 data-nosnippet>95</a> </span><span class="kw">pub</span>(<span class="kw">crate</span>) <span class="kw">fn </span>new(r: <span class="kw-2">&amp;</span><span class="kw">impl </span>Remappable, stride2: usize) -&gt; Remapper {
<a href=#96 id=96 data-nosnippet>96</a> <span class="kw">let </span>idx = IndexMapper { stride2 };
<a href=#97 id=97 data-nosnippet>97</a> <span class="kw">let </span>map = (<span class="number">0</span>..r.state_len()).map(|i| idx.to_state_id(i)).collect();
<a href=#98 id=98 data-nosnippet>98</a> Remapper { map, idx }
<a href=#99 id=99 data-nosnippet>99</a> }
<a href=#100 id=100 data-nosnippet>100</a>
<a href=#101 id=101 data-nosnippet>101</a> <span class="doccomment">/// Swap two states. Once this is called, callers must follow through to
<a href=#102 id=102 data-nosnippet>102</a> /// call `remap`, or else it's possible for the underlying remappable
<a href=#103 id=103 data-nosnippet>103</a> /// value to be in a corrupt state.
<a href=#104 id=104 data-nosnippet>104</a> </span><span class="kw">pub</span>(<span class="kw">crate</span>) <span class="kw">fn </span>swap(
<a href=#105 id=105 data-nosnippet>105</a> <span class="kw-2">&amp;mut </span><span class="self">self</span>,
<a href=#106 id=106 data-nosnippet>106</a> r: <span class="kw-2">&amp;mut </span><span class="kw">impl </span>Remappable,
<a href=#107 id=107 data-nosnippet>107</a> id1: StateID,
<a href=#108 id=108 data-nosnippet>108</a> id2: StateID,
<a href=#109 id=109 data-nosnippet>109</a> ) {
<a href=#110 id=110 data-nosnippet>110</a> <span class="kw">if </span>id1 == id2 {
<a href=#111 id=111 data-nosnippet>111</a> <span class="kw">return</span>;
<a href=#112 id=112 data-nosnippet>112</a> }
<a href=#113 id=113 data-nosnippet>113</a> r.swap_states(id1, id2);
<a href=#114 id=114 data-nosnippet>114</a> <span class="self">self</span>.map.swap(<span class="self">self</span>.idx.to_index(id1), <span class="self">self</span>.idx.to_index(id2));
<a href=#115 id=115 data-nosnippet>115</a> }
<a href=#116 id=116 data-nosnippet>116</a>
<a href=#117 id=117 data-nosnippet>117</a> <span class="doccomment">/// Complete the remapping process by rewriting all state IDs in the
<a href=#118 id=118 data-nosnippet>118</a> /// remappable value according to the swaps performed.
<a href=#119 id=119 data-nosnippet>119</a> </span><span class="kw">pub</span>(<span class="kw">crate</span>) <span class="kw">fn </span>remap(<span class="kw-2">mut </span><span class="self">self</span>, r: <span class="kw-2">&amp;mut </span><span class="kw">impl </span>Remappable) {
<a href=#120 id=120 data-nosnippet>120</a> <span class="comment">// Update the map to account for states that have been swapped
<a href=#121 id=121 data-nosnippet>121</a> // multiple times. For example, if (A, C) and (C, G) are swapped, then
<a href=#122 id=122 data-nosnippet>122</a> // transitions previously pointing to A should now point to G. But if
<a href=#123 id=123 data-nosnippet>123</a> // we don't update our map, they will erroneously be set to C. All we
<a href=#124 id=124 data-nosnippet>124</a> // do is follow the swaps in our map until we see our original state
<a href=#125 id=125 data-nosnippet>125</a> // ID.
<a href=#126 id=126 data-nosnippet>126</a> //
<a href=#127 id=127 data-nosnippet>127</a> // The intuition here is to think about how changes are made to the
<a href=#128 id=128 data-nosnippet>128</a> // map: only through pairwise swaps. That means that starting at any
<a href=#129 id=129 data-nosnippet>129</a> // given state, it is always possible to find the loop back to that
<a href=#130 id=130 data-nosnippet>130</a> // state by following the swaps represented in the map (which might be
<a href=#131 id=131 data-nosnippet>131</a> // 0 swaps).
<a href=#132 id=132 data-nosnippet>132</a> //
<a href=#133 id=133 data-nosnippet>133</a> // We are also careful to clone the map before starting in order to
<a href=#134 id=134 data-nosnippet>134</a> // freeze it. We use the frozen map to find our loops, since we need to
<a href=#135 id=135 data-nosnippet>135</a> // update our map as well. Without freezing it, our updates could break
<a href=#136 id=136 data-nosnippet>136</a> // the loops referenced above and produce incorrect results.
<a href=#137 id=137 data-nosnippet>137</a> </span><span class="kw">let </span>oldmap = <span class="self">self</span>.map.clone();
<a href=#138 id=138 data-nosnippet>138</a> <span class="kw">for </span>i <span class="kw">in </span><span class="number">0</span>..r.state_len() {
<a href=#139 id=139 data-nosnippet>139</a> <span class="kw">let </span>cur_id = <span class="self">self</span>.idx.to_state_id(i);
<a href=#140 id=140 data-nosnippet>140</a> <span class="kw">let </span><span class="kw-2">mut </span>new_id = oldmap[i];
<a href=#141 id=141 data-nosnippet>141</a> <span class="kw">if </span>cur_id == new_id {
<a href=#142 id=142 data-nosnippet>142</a> <span class="kw">continue</span>;
<a href=#143 id=143 data-nosnippet>143</a> }
<a href=#144 id=144 data-nosnippet>144</a> <span class="kw">loop </span>{
<a href=#145 id=145 data-nosnippet>145</a> <span class="kw">let </span>id = oldmap[<span class="self">self</span>.idx.to_index(new_id)];
<a href=#146 id=146 data-nosnippet>146</a> <span class="kw">if </span>cur_id == id {
<a href=#147 id=147 data-nosnippet>147</a> <span class="self">self</span>.map[i] = new_id;
<a href=#148 id=148 data-nosnippet>148</a> <span class="kw">break</span>;
<a href=#149 id=149 data-nosnippet>149</a> }
<a href=#150 id=150 data-nosnippet>150</a> new_id = id;
<a href=#151 id=151 data-nosnippet>151</a> }
<a href=#152 id=152 data-nosnippet>152</a> }
<a href=#153 id=153 data-nosnippet>153</a> r.remap(|sid| <span class="self">self</span>.map[<span class="self">self</span>.idx.to_index(sid)]);
<a href=#154 id=154 data-nosnippet>154</a> }
<a href=#155 id=155 data-nosnippet>155</a>}
<a href=#156 id=156 data-nosnippet>156</a>
<a href=#157 id=157 data-nosnippet>157</a><span class="doccomment">/// A simple type for mapping between state indices and state IDs.
<a href=#158 id=158 data-nosnippet>158</a>///
<a href=#159 id=159 data-nosnippet>159</a>/// The reason why this exists is because state IDs are "premultiplied" in a
<a href=#160 id=160 data-nosnippet>160</a>/// DFA. That is, in order to get to the transitions for a particular state,
<a href=#161 id=161 data-nosnippet>161</a>/// one need only use the state ID as-is, instead of having to multiply it by
<a href=#162 id=162 data-nosnippet>162</a>/// transition table's stride.
<a href=#163 id=163 data-nosnippet>163</a>///
<a href=#164 id=164 data-nosnippet>164</a>/// The downside of this is that it's inconvenient to map between state IDs
<a href=#165 id=165 data-nosnippet>165</a>/// using a dense map, e.g., Vec&lt;StateID&gt;. That's because state IDs look like
<a href=#166 id=166 data-nosnippet>166</a>/// `0`, `stride`, `2*stride`, `3*stride`, etc., instead of `0`, `1`, `2`, `3`,
<a href=#167 id=167 data-nosnippet>167</a>/// etc.
<a href=#168 id=168 data-nosnippet>168</a>///
<a href=#169 id=169 data-nosnippet>169</a>/// Since our state IDs are premultiplied, we can convert back-and-forth
<a href=#170 id=170 data-nosnippet>170</a>/// between IDs and indices by simply unmultiplying the IDs and multiplying the
<a href=#171 id=171 data-nosnippet>171</a>/// indices.
<a href=#172 id=172 data-nosnippet>172</a>///
<a href=#173 id=173 data-nosnippet>173</a>/// Note that for a sparse NFA, state IDs and indices are equivalent. In this
<a href=#174 id=174 data-nosnippet>174</a>/// case, we set the stride of the index mapped to be `0`, which acts as an
<a href=#175 id=175 data-nosnippet>175</a>/// identity.
<a href=#176 id=176 data-nosnippet>176</a></span><span class="attr">#[derive(Debug)]
<a href=#177 id=177 data-nosnippet>177</a></span><span class="kw">struct </span>IndexMapper {
<a href=#178 id=178 data-nosnippet>178</a> <span class="doccomment">/// The power of 2 corresponding to the stride of the corresponding
<a href=#179 id=179 data-nosnippet>179</a> /// transition table. 'id &gt;&gt; stride2' de-multiplies an ID while 'index &lt;&lt;
<a href=#180 id=180 data-nosnippet>180</a> /// stride2' pre-multiplies an index to an ID.
<a href=#181 id=181 data-nosnippet>181</a> </span>stride2: usize,
<a href=#182 id=182 data-nosnippet>182</a>}
<a href=#183 id=183 data-nosnippet>183</a>
<a href=#184 id=184 data-nosnippet>184</a><span class="kw">impl </span>IndexMapper {
<a href=#185 id=185 data-nosnippet>185</a> <span class="doccomment">/// Convert a state ID to a state index.
<a href=#186 id=186 data-nosnippet>186</a> </span><span class="kw">fn </span>to_index(<span class="kw-2">&amp;</span><span class="self">self</span>, id: StateID) -&gt; usize {
<a href=#187 id=187 data-nosnippet>187</a> id.as_usize() &gt;&gt; <span class="self">self</span>.stride2
<a href=#188 id=188 data-nosnippet>188</a> }
<a href=#189 id=189 data-nosnippet>189</a>
<a href=#190 id=190 data-nosnippet>190</a> <span class="doccomment">/// Convert a state index to a state ID.
<a href=#191 id=191 data-nosnippet>191</a> </span><span class="kw">fn </span>to_state_id(<span class="kw-2">&amp;</span><span class="self">self</span>, index: usize) -&gt; StateID {
<a href=#192 id=192 data-nosnippet>192</a> <span class="comment">// CORRECTNESS: If the given index is not valid, then it is not
<a href=#193 id=193 data-nosnippet>193</a> // required for this to panic or return a valid state ID. We'll "just"
<a href=#194 id=194 data-nosnippet>194</a> // wind up with panics or silent logic errors at some other point. But
<a href=#195 id=195 data-nosnippet>195</a> // this is OK because if Remappable::state_len is correct and so is
<a href=#196 id=196 data-nosnippet>196</a> // 'to_index', then all inputs to 'to_state_id' should be valid indices
<a href=#197 id=197 data-nosnippet>197</a> // and thus transform into valid state IDs.
<a href=#198 id=198 data-nosnippet>198</a> </span>StateID::new_unchecked(index &lt;&lt; <span class="self">self</span>.stride2)
<a href=#199 id=199 data-nosnippet>199</a> }
<a href=#200 id=200 data-nosnippet>200</a>}
<a href=#201 id=201 data-nosnippet>201</a>
<a href=#202 id=202 data-nosnippet>202</a><span class="kw">impl </span>Remappable <span class="kw">for </span>noncontiguous::NFA {
<a href=#203 id=203 data-nosnippet>203</a> <span class="kw">fn </span>state_len(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; usize {
<a href=#204 id=204 data-nosnippet>204</a> noncontiguous::NFA::states(<span class="self">self</span>).len()
<a href=#205 id=205 data-nosnippet>205</a> }
<a href=#206 id=206 data-nosnippet>206</a>
<a href=#207 id=207 data-nosnippet>207</a> <span class="kw">fn </span>swap_states(<span class="kw-2">&amp;mut </span><span class="self">self</span>, id1: StateID, id2: StateID) {
<a href=#208 id=208 data-nosnippet>208</a> noncontiguous::NFA::swap_states(<span class="self">self</span>, id1, id2)
<a href=#209 id=209 data-nosnippet>209</a> }
<a href=#210 id=210 data-nosnippet>210</a>
<a href=#211 id=211 data-nosnippet>211</a> <span class="kw">fn </span>remap(<span class="kw-2">&amp;mut </span><span class="self">self</span>, map: <span class="kw">impl </span>Fn(StateID) -&gt; StateID) {
<a href=#212 id=212 data-nosnippet>212</a> noncontiguous::NFA::remap(<span class="self">self</span>, map)
<a href=#213 id=213 data-nosnippet>213</a> }
<a href=#214 id=214 data-nosnippet>214</a>}
</code></pre></div></section></main></body></html>

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,43 @@
<!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 `/home/newkirk/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/aho-corasick-1.1.4/src/util/special.rs`."><title>special.rs - source</title><script>if(window.location.protocol!=="file:")document.head.insertAdjacentHTML("beforeend","SourceSerif4-Regular-6b053e98.ttf.woff2,FiraSans-Italic-81dc35de.woff2,FiraSans-Regular-0fe48ade.woff2,FiraSans-MediumItalic-ccf7e434.woff2,FiraSans-Medium-e1aa3f0a.woff2,SourceCodePro-Regular-8badfe75.ttf.woff2,SourceCodePro-Semibold-aa29a496.ttf.woff2".split(",").map(f=>`<link rel="preload" as="font" type="font/woff2"href="../../../static.files/${f}">`).join(""))</script><link rel="stylesheet" href="../../../static.files/normalize-9960930a.css"><link rel="stylesheet" href="../../../static.files/rustdoc-ca0dd0c4.css"><meta name="rustdoc-vars" data-root-path="../../../" data-static-root-path="../../../static.files/" data-current-crate="aho_corasick" data-themes="" data-resource-suffix="" data-rustdoc-version="1.93.1 (01f6ddf75 2026-02-11) (Arch Linux rust 1:1.93.1-1)" data-channel="1.93.1" data-search-js="search-9e2438ea.js" data-stringdex-js="stringdex-a3946164.js" data-settings-js="settings-c38705f0.js" ><script src="../../../static.files/storage-e2aeef58.js"></script><script defer src="../../../static.files/src-script-813739b1.js"></script><script defer src="../../../src-files.js"></script><script defer src="../../../static.files/main-a410ff4d.js"></script><noscript><link rel="stylesheet" href="../../../static.files/noscript-263c88ec.css"></noscript><link rel="alternate icon" type="image/png" href="../../../static.files/favicon-32x32-eab170b8.png"><link rel="icon" type="image/svg+xml" href="../../../static.files/favicon-044be391.svg"></head><body class="rustdoc src"><!--[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="src-sidebar-title"><h2>Files</h2></div></nav><div class="sidebar-resizer" title="Drag to resize sidebar"></div><main><section id="main-content" class="content"><div class="main-heading"><h1><div class="sub-heading">aho_corasick/util/</div>special.rs</h1><rustdoc-toolbar></rustdoc-toolbar></div><div class="example-wrap digits-2"><pre class="rust"><code><a href=#1 id=1 data-nosnippet>1</a><span class="kw">use </span><span class="kw">crate</span>::util::primitives::StateID;
<a href=#2 id=2 data-nosnippet>2</a>
<a href=#3 id=3 data-nosnippet>3</a><span class="doccomment">/// A collection of sentinel state IDs for Aho-Corasick automata.
<a href=#4 id=4 data-nosnippet>4</a>///
<a href=#5 id=5 data-nosnippet>5</a>/// This specifically enables the technique by which we determine which states
<a href=#6 id=6 data-nosnippet>6</a>/// are dead, matches or start states. Namely, by arranging states in a
<a href=#7 id=7 data-nosnippet>7</a>/// particular order, we can determine the type of a state simply by looking at
<a href=#8 id=8 data-nosnippet>8</a>/// its ID.
<a href=#9 id=9 data-nosnippet>9</a></span><span class="attr">#[derive(Clone, Debug)]
<a href=#10 id=10 data-nosnippet>10</a></span><span class="kw">pub</span>(<span class="kw">crate</span>) <span class="kw">struct </span>Special {
<a href=#11 id=11 data-nosnippet>11</a> <span class="doccomment">/// The maximum ID of all the "special" states. This corresponds either to
<a href=#12 id=12 data-nosnippet>12</a> /// start_anchored_id when a prefilter is active and max_match_id when a
<a href=#13 id=13 data-nosnippet>13</a> /// prefilter is not active. The idea here is that if there is no prefilter,
<a href=#14 id=14 data-nosnippet>14</a> /// then there is no point in treating start states as special.
<a href=#15 id=15 data-nosnippet>15</a> </span><span class="kw">pub</span>(<span class="kw">crate</span>) max_special_id: StateID,
<a href=#16 id=16 data-nosnippet>16</a> <span class="doccomment">/// The maximum ID of all the match states. Any state ID bigger than this
<a href=#17 id=17 data-nosnippet>17</a> /// is guaranteed to be a non-match ID.
<a href=#18 id=18 data-nosnippet>18</a> ///
<a href=#19 id=19 data-nosnippet>19</a> /// It is possible and legal for max_match_id to be equal to
<a href=#20 id=20 data-nosnippet>20</a> /// start_anchored_id, which occurs precisely in the case where the empty
<a href=#21 id=21 data-nosnippet>21</a> /// string is a pattern that was added to the underlying automaton.
<a href=#22 id=22 data-nosnippet>22</a> </span><span class="kw">pub</span>(<span class="kw">crate</span>) max_match_id: StateID,
<a href=#23 id=23 data-nosnippet>23</a> <span class="doccomment">/// The state ID of the start state used for unanchored searches.
<a href=#24 id=24 data-nosnippet>24</a> </span><span class="kw">pub</span>(<span class="kw">crate</span>) start_unanchored_id: StateID,
<a href=#25 id=25 data-nosnippet>25</a> <span class="doccomment">/// The state ID of the start state used for anchored searches. This is
<a href=#26 id=26 data-nosnippet>26</a> /// always start_unanchored_id+1.
<a href=#27 id=27 data-nosnippet>27</a> </span><span class="kw">pub</span>(<span class="kw">crate</span>) start_anchored_id: StateID,
<a href=#28 id=28 data-nosnippet>28</a>}
<a href=#29 id=29 data-nosnippet>29</a>
<a href=#30 id=30 data-nosnippet>30</a><span class="kw">impl </span>Special {
<a href=#31 id=31 data-nosnippet>31</a> <span class="doccomment">/// Create a new set of "special" state IDs with all IDs initialized to
<a href=#32 id=32 data-nosnippet>32</a> /// zero. The general idea here is that they will be updated and set to
<a href=#33 id=33 data-nosnippet>33</a> /// correct values later.
<a href=#34 id=34 data-nosnippet>34</a> </span><span class="kw">pub</span>(<span class="kw">crate</span>) <span class="kw">fn </span>zero() -&gt; Special {
<a href=#35 id=35 data-nosnippet>35</a> Special {
<a href=#36 id=36 data-nosnippet>36</a> max_special_id: StateID::ZERO,
<a href=#37 id=37 data-nosnippet>37</a> max_match_id: StateID::ZERO,
<a href=#38 id=38 data-nosnippet>38</a> start_unanchored_id: StateID::ZERO,
<a href=#39 id=39 data-nosnippet>39</a> start_anchored_id: StateID::ZERO,
<a href=#40 id=40 data-nosnippet>40</a> }
<a href=#41 id=41 data-nosnippet>41</a> }
<a href=#42 id=42 data-nosnippet>42</a>}
</code></pre></div></section></main></body></html>