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

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,836 @@
<!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/dfa.rs`."><title>dfa.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/</div>dfa.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>Provides direct access to a DFA implementation of Aho-Corasick.
<a href=#3 id=3 data-nosnippet>3</a>
<a href=#4 id=4 data-nosnippet>4</a>This is a low-level API that generally only needs to be used in niche
<a href=#5 id=5 data-nosnippet>5</a>circumstances. When possible, prefer using [`AhoCorasick`](crate::AhoCorasick)
<a href=#6 id=6 data-nosnippet>6</a>instead of a DFA directly. Using an `DFA` directly is typically only necessary
<a href=#7 id=7 data-nosnippet>7</a>when one needs access to the [`Automaton`] trait implementation.
<a href=#8 id=8 data-nosnippet>8</a>*/
<a href=#9 id=9 data-nosnippet>9</a>
<a href=#10 id=10 data-nosnippet>10</a></span><span class="kw">use </span>alloc::{vec, vec::Vec};
<a href=#11 id=11 data-nosnippet>11</a>
<a href=#12 id=12 data-nosnippet>12</a><span class="kw">use crate</span>::{
<a href=#13 id=13 data-nosnippet>13</a> automaton::Automaton,
<a href=#14 id=14 data-nosnippet>14</a> nfa::noncontiguous,
<a href=#15 id=15 data-nosnippet>15</a> util::{
<a href=#16 id=16 data-nosnippet>16</a> alphabet::ByteClasses,
<a href=#17 id=17 data-nosnippet>17</a> error::{BuildError, MatchError},
<a href=#18 id=18 data-nosnippet>18</a> int::{Usize, U32},
<a href=#19 id=19 data-nosnippet>19</a> prefilter::Prefilter,
<a href=#20 id=20 data-nosnippet>20</a> primitives::{IteratorIndexExt, PatternID, SmallIndex, StateID},
<a href=#21 id=21 data-nosnippet>21</a> search::{Anchored, MatchKind, StartKind},
<a href=#22 id=22 data-nosnippet>22</a> special::Special,
<a href=#23 id=23 data-nosnippet>23</a> },
<a href=#24 id=24 data-nosnippet>24</a>};
<a href=#25 id=25 data-nosnippet>25</a>
<a href=#26 id=26 data-nosnippet>26</a><span class="doccomment">/// A DFA implementation of Aho-Corasick.
<a href=#27 id=27 data-nosnippet>27</a>///
<a href=#28 id=28 data-nosnippet>28</a>/// When possible, prefer using [`AhoCorasick`](crate::AhoCorasick) instead of
<a href=#29 id=29 data-nosnippet>29</a>/// this type directly. Using a `DFA` directly is typically only necessary when
<a href=#30 id=30 data-nosnippet>30</a>/// one needs access to the [`Automaton`] trait implementation.
<a href=#31 id=31 data-nosnippet>31</a>///
<a href=#32 id=32 data-nosnippet>32</a>/// This DFA can only be built by first constructing a [`noncontiguous::NFA`].
<a href=#33 id=33 data-nosnippet>33</a>/// Both [`DFA::new`] and [`Builder::build`] do this for you automatically, but
<a href=#34 id=34 data-nosnippet>34</a>/// [`Builder::build_from_noncontiguous`] permits doing it explicitly.
<a href=#35 id=35 data-nosnippet>35</a>///
<a href=#36 id=36 data-nosnippet>36</a>/// A DFA provides the best possible search performance (in this crate) via two
<a href=#37 id=37 data-nosnippet>37</a>/// mechanisms:
<a href=#38 id=38 data-nosnippet>38</a>///
<a href=#39 id=39 data-nosnippet>39</a>/// * All states use a dense representation for their transitions.
<a href=#40 id=40 data-nosnippet>40</a>/// * All failure transitions are pre-computed such that they are never
<a href=#41 id=41 data-nosnippet>41</a>/// explicitly handled at search time.
<a href=#42 id=42 data-nosnippet>42</a>///
<a href=#43 id=43 data-nosnippet>43</a>/// These two facts combined mean that every state transition is performed
<a href=#44 id=44 data-nosnippet>44</a>/// using a constant number of instructions. However, this comes at
<a href=#45 id=45 data-nosnippet>45</a>/// great cost. The memory usage of a DFA can be quite exorbitant.
<a href=#46 id=46 data-nosnippet>46</a>/// It is potentially multiple orders of magnitude greater than a
<a href=#47 id=47 data-nosnippet>47</a>/// [`contiguous::NFA`](crate::nfa::contiguous::NFA) for example. In exchange,
<a href=#48 id=48 data-nosnippet>48</a>/// a DFA will typically have better search speed than a `contiguous::NFA`, but
<a href=#49 id=49 data-nosnippet>49</a>/// not by orders of magnitude.
<a href=#50 id=50 data-nosnippet>50</a>///
<a href=#51 id=51 data-nosnippet>51</a>/// Unless you have a small number of patterns or memory usage is not a concern
<a href=#52 id=52 data-nosnippet>52</a>/// and search performance is critical, a DFA is usually not the best choice.
<a href=#53 id=53 data-nosnippet>53</a>///
<a href=#54 id=54 data-nosnippet>54</a>/// Moreover, unlike the NFAs in this crate, it is costly for a DFA to
<a href=#55 id=55 data-nosnippet>55</a>/// support for anchored and unanchored search configurations. Namely,
<a href=#56 id=56 data-nosnippet>56</a>/// since failure transitions are pre-computed, supporting both anchored
<a href=#57 id=57 data-nosnippet>57</a>/// and unanchored searches requires a duplication of the transition table,
<a href=#58 id=58 data-nosnippet>58</a>/// making the memory usage of such a DFA ever bigger. (The NFAs in this crate
<a href=#59 id=59 data-nosnippet>59</a>/// unconditionally support both anchored and unanchored searches because there
<a href=#60 id=60 data-nosnippet>60</a>/// is essentially no added cost for doing so.) It is for this reason that
<a href=#61 id=61 data-nosnippet>61</a>/// a DFA's support for anchored and unanchored searches can be configured
<a href=#62 id=62 data-nosnippet>62</a>/// via [`Builder::start_kind`]. By default, a DFA only supports unanchored
<a href=#63 id=63 data-nosnippet>63</a>/// searches.
<a href=#64 id=64 data-nosnippet>64</a>///
<a href=#65 id=65 data-nosnippet>65</a>/// # Example
<a href=#66 id=66 data-nosnippet>66</a>///
<a href=#67 id=67 data-nosnippet>67</a>/// This example shows how to build an `DFA` directly and use it to execute
<a href=#68 id=68 data-nosnippet>68</a>/// [`Automaton::try_find`]:
<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>/// use aho_corasick::{
<a href=#72 id=72 data-nosnippet>72</a>/// automaton::Automaton,
<a href=#73 id=73 data-nosnippet>73</a>/// dfa::DFA,
<a href=#74 id=74 data-nosnippet>74</a>/// Input, Match,
<a href=#75 id=75 data-nosnippet>75</a>/// };
<a href=#76 id=76 data-nosnippet>76</a>///
<a href=#77 id=77 data-nosnippet>77</a>/// let patterns = &amp;["b", "abc", "abcd"];
<a href=#78 id=78 data-nosnippet>78</a>/// let haystack = "abcd";
<a href=#79 id=79 data-nosnippet>79</a>///
<a href=#80 id=80 data-nosnippet>80</a>/// let nfa = DFA::new(patterns).unwrap();
<a href=#81 id=81 data-nosnippet>81</a>/// assert_eq!(
<a href=#82 id=82 data-nosnippet>82</a>/// Some(Match::must(0, 1..2)),
<a href=#83 id=83 data-nosnippet>83</a>/// nfa.try_find(&amp;Input::new(haystack))?,
<a href=#84 id=84 data-nosnippet>84</a>/// );
<a href=#85 id=85 data-nosnippet>85</a>/// # Ok::&lt;(), Box&lt;dyn std::error::Error&gt;&gt;(())
<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>/// It is also possible to implement your own version of `try_find`. See the
<a href=#89 id=89 data-nosnippet>89</a>/// [`Automaton`] documentation for an example.
<a href=#90 id=90 data-nosnippet>90</a></span><span class="attr">#[derive(Clone)]
<a href=#91 id=91 data-nosnippet>91</a></span><span class="kw">pub struct </span>DFA {
<a href=#92 id=92 data-nosnippet>92</a> <span class="doccomment">/// The DFA transition table. IDs in this table are pre-multiplied. So
<a href=#93 id=93 data-nosnippet>93</a> /// instead of the IDs being 0, 1, 2, 3, ..., they are 0*stride, 1*stride,
<a href=#94 id=94 data-nosnippet>94</a> /// 2*stride, 3*stride, ...
<a href=#95 id=95 data-nosnippet>95</a> </span>trans: Vec&lt;StateID&gt;,
<a href=#96 id=96 data-nosnippet>96</a> <span class="doccomment">/// The matches for every match state in this DFA. This is first indexed by
<a href=#97 id=97 data-nosnippet>97</a> /// state index (so that's `sid &gt;&gt; stride2`) and then by order in which the
<a href=#98 id=98 data-nosnippet>98</a> /// matches are meant to occur.
<a href=#99 id=99 data-nosnippet>99</a> </span>matches: Vec&lt;Vec&lt;PatternID&gt;&gt;,
<a href=#100 id=100 data-nosnippet>100</a> <span class="doccomment">/// The amount of heap memory used, in bytes, by the inner Vecs of
<a href=#101 id=101 data-nosnippet>101</a> /// 'matches'.
<a href=#102 id=102 data-nosnippet>102</a> </span>matches_memory_usage: usize,
<a href=#103 id=103 data-nosnippet>103</a> <span class="doccomment">/// The length of each pattern. This is used to compute the start offset
<a href=#104 id=104 data-nosnippet>104</a> /// of a match.
<a href=#105 id=105 data-nosnippet>105</a> </span>pattern_lens: Vec&lt;SmallIndex&gt;,
<a href=#106 id=106 data-nosnippet>106</a> <span class="doccomment">/// A prefilter for accelerating searches, if one exists.
<a href=#107 id=107 data-nosnippet>107</a> </span>prefilter: <span class="prelude-ty">Option</span>&lt;Prefilter&gt;,
<a href=#108 id=108 data-nosnippet>108</a> <span class="doccomment">/// The match semantics built into this DFA.
<a href=#109 id=109 data-nosnippet>109</a> </span>match_kind: MatchKind,
<a href=#110 id=110 data-nosnippet>110</a> <span class="doccomment">/// The total number of states in this DFA.
<a href=#111 id=111 data-nosnippet>111</a> </span>state_len: usize,
<a href=#112 id=112 data-nosnippet>112</a> <span class="doccomment">/// The alphabet size, or total number of equivalence classes, for this
<a href=#113 id=113 data-nosnippet>113</a> /// DFA. Note that the actual number of transitions in each state is
<a href=#114 id=114 data-nosnippet>114</a> /// stride=2^stride2, where stride is the smallest power of 2 greater than
<a href=#115 id=115 data-nosnippet>115</a> /// or equal to alphabet_len. We do things this way so that we can use
<a href=#116 id=116 data-nosnippet>116</a> /// bitshifting to go from a state ID to an index into 'matches'.
<a href=#117 id=117 data-nosnippet>117</a> </span>alphabet_len: usize,
<a href=#118 id=118 data-nosnippet>118</a> <span class="doccomment">/// The exponent with a base 2, such that stride=2^stride2. Given a state
<a href=#119 id=119 data-nosnippet>119</a> /// index 'i', its state identifier is 'i &lt;&lt; stride2'. Given a state
<a href=#120 id=120 data-nosnippet>120</a> /// identifier 'sid', its state index is 'sid &gt;&gt; stride2'.
<a href=#121 id=121 data-nosnippet>121</a> </span>stride2: usize,
<a href=#122 id=122 data-nosnippet>122</a> <span class="doccomment">/// The equivalence classes for this DFA. All transitions are defined on
<a href=#123 id=123 data-nosnippet>123</a> /// equivalence classes and not on the 256 distinct byte values.
<a href=#124 id=124 data-nosnippet>124</a> </span>byte_classes: ByteClasses,
<a href=#125 id=125 data-nosnippet>125</a> <span class="doccomment">/// The length of the shortest pattern in this automaton.
<a href=#126 id=126 data-nosnippet>126</a> </span>min_pattern_len: usize,
<a href=#127 id=127 data-nosnippet>127</a> <span class="doccomment">/// The length of the longest pattern in this automaton.
<a href=#128 id=128 data-nosnippet>128</a> </span>max_pattern_len: usize,
<a href=#129 id=129 data-nosnippet>129</a> <span class="doccomment">/// The information required to deduce which states are "special" in this
<a href=#130 id=130 data-nosnippet>130</a> /// DFA.
<a href=#131 id=131 data-nosnippet>131</a> </span>special: Special,
<a href=#132 id=132 data-nosnippet>132</a>}
<a href=#133 id=133 data-nosnippet>133</a>
<a href=#134 id=134 data-nosnippet>134</a><span class="kw">impl </span>DFA {
<a href=#135 id=135 data-nosnippet>135</a> <span class="doccomment">/// Create a new Aho-Corasick DFA using the default configuration.
<a href=#136 id=136 data-nosnippet>136</a> ///
<a href=#137 id=137 data-nosnippet>137</a> /// Use a [`Builder`] if you want to change the configuration.
<a href=#138 id=138 data-nosnippet>138</a> </span><span class="kw">pub fn </span>new&lt;I, P&gt;(patterns: I) -&gt; <span class="prelude-ty">Result</span>&lt;DFA, BuildError&gt;
<a href=#139 id=139 data-nosnippet>139</a> <span class="kw">where
<a href=#140 id=140 data-nosnippet>140</a> </span>I: IntoIterator&lt;Item = P&gt;,
<a href=#141 id=141 data-nosnippet>141</a> P: AsRef&lt;[u8]&gt;,
<a href=#142 id=142 data-nosnippet>142</a> {
<a href=#143 id=143 data-nosnippet>143</a> DFA::builder().build(patterns)
<a href=#144 id=144 data-nosnippet>144</a> }
<a href=#145 id=145 data-nosnippet>145</a>
<a href=#146 id=146 data-nosnippet>146</a> <span class="doccomment">/// A convenience method for returning a new Aho-Corasick DFA builder.
<a href=#147 id=147 data-nosnippet>147</a> ///
<a href=#148 id=148 data-nosnippet>148</a> /// This usually permits one to just import the `DFA` type.
<a href=#149 id=149 data-nosnippet>149</a> </span><span class="kw">pub fn </span>builder() -&gt; Builder {
<a href=#150 id=150 data-nosnippet>150</a> Builder::new()
<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>
<a href=#154 id=154 data-nosnippet>154</a><span class="kw">impl </span>DFA {
<a href=#155 id=155 data-nosnippet>155</a> <span class="doccomment">/// A sentinel state ID indicating that a search should stop once it has
<a href=#156 id=156 data-nosnippet>156</a> /// entered this state. When a search stops, it returns a match if one has
<a href=#157 id=157 data-nosnippet>157</a> /// been found, otherwise no match. A DFA always has an actual dead state
<a href=#158 id=158 data-nosnippet>158</a> /// at this ID.
<a href=#159 id=159 data-nosnippet>159</a> ///
<a href=#160 id=160 data-nosnippet>160</a> /// N.B. DFAs, unlike NFAs, do not have any notion of a FAIL state.
<a href=#161 id=161 data-nosnippet>161</a> /// Namely, the whole point of a DFA is that the FAIL state is completely
<a href=#162 id=162 data-nosnippet>162</a> /// compiled away. That is, DFA construction involves pre-computing the
<a href=#163 id=163 data-nosnippet>163</a> /// failure transitions everywhere, such that failure transitions are no
<a href=#164 id=164 data-nosnippet>164</a> /// longer used at search time. This, combined with its uniformly dense
<a href=#165 id=165 data-nosnippet>165</a> /// representation, are the two most important factors in why it's faster
<a href=#166 id=166 data-nosnippet>166</a> /// than the NFAs in this crate.
<a href=#167 id=167 data-nosnippet>167</a> </span><span class="kw">const </span>DEAD: StateID = StateID::new_unchecked(<span class="number">0</span>);
<a href=#168 id=168 data-nosnippet>168</a>
<a href=#169 id=169 data-nosnippet>169</a> <span class="doccomment">/// Adds the given pattern IDs as matches to the given state and also
<a href=#170 id=170 data-nosnippet>170</a> /// records the added memory usage.
<a href=#171 id=171 data-nosnippet>171</a> </span><span class="kw">fn </span>set_matches(
<a href=#172 id=172 data-nosnippet>172</a> <span class="kw-2">&amp;mut </span><span class="self">self</span>,
<a href=#173 id=173 data-nosnippet>173</a> sid: StateID,
<a href=#174 id=174 data-nosnippet>174</a> pids: <span class="kw">impl </span>Iterator&lt;Item = PatternID&gt;,
<a href=#175 id=175 data-nosnippet>175</a> ) {
<a href=#176 id=176 data-nosnippet>176</a> <span class="kw">let </span>index = (sid.as_usize() &gt;&gt; <span class="self">self</span>.stride2).checked_sub(<span class="number">2</span>).unwrap();
<a href=#177 id=177 data-nosnippet>177</a> <span class="kw">let </span><span class="kw-2">mut </span>at_least_one = <span class="bool-val">false</span>;
<a href=#178 id=178 data-nosnippet>178</a> <span class="kw">for </span>pid <span class="kw">in </span>pids {
<a href=#179 id=179 data-nosnippet>179</a> <span class="self">self</span>.matches[index].push(pid);
<a href=#180 id=180 data-nosnippet>180</a> <span class="self">self</span>.matches_memory_usage += PatternID::SIZE;
<a href=#181 id=181 data-nosnippet>181</a> at_least_one = <span class="bool-val">true</span>;
<a href=#182 id=182 data-nosnippet>182</a> }
<a href=#183 id=183 data-nosnippet>183</a> <span class="macro">assert!</span>(at_least_one, <span class="string">"match state must have non-empty pids"</span>);
<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>
<a href=#187 id=187 data-nosnippet>187</a><span class="comment">// SAFETY: 'start_state' always returns a valid state ID, 'next_state' always
<a href=#188 id=188 data-nosnippet>188</a>// returns a valid state ID given a valid state ID. We otherwise claim that
<a href=#189 id=189 data-nosnippet>189</a>// all other methods are correct as well.
<a href=#190 id=190 data-nosnippet>190</a></span><span class="kw">unsafe impl </span>Automaton <span class="kw">for </span>DFA {
<a href=#191 id=191 data-nosnippet>191</a> <span class="attr">#[inline(always)]
<a href=#192 id=192 data-nosnippet>192</a> </span><span class="kw">fn </span>start_state(<span class="kw-2">&amp;</span><span class="self">self</span>, anchored: Anchored) -&gt; <span class="prelude-ty">Result</span>&lt;StateID, MatchError&gt; {
<a href=#193 id=193 data-nosnippet>193</a> <span class="comment">// Either of the start state IDs can be DEAD, in which case, support
<a href=#194 id=194 data-nosnippet>194</a> // for that type of search is not provided by this DFA. Which start
<a href=#195 id=195 data-nosnippet>195</a> // state IDs are inactive depends on the 'StartKind' configuration at
<a href=#196 id=196 data-nosnippet>196</a> // DFA construction time.
<a href=#197 id=197 data-nosnippet>197</a> </span><span class="kw">match </span>anchored {
<a href=#198 id=198 data-nosnippet>198</a> Anchored::No =&gt; {
<a href=#199 id=199 data-nosnippet>199</a> <span class="kw">let </span>start = <span class="self">self</span>.special.start_unanchored_id;
<a href=#200 id=200 data-nosnippet>200</a> <span class="kw">if </span>start == DFA::DEAD {
<a href=#201 id=201 data-nosnippet>201</a> <span class="prelude-val">Err</span>(MatchError::invalid_input_unanchored())
<a href=#202 id=202 data-nosnippet>202</a> } <span class="kw">else </span>{
<a href=#203 id=203 data-nosnippet>203</a> <span class="prelude-val">Ok</span>(start)
<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> Anchored::Yes =&gt; {
<a href=#207 id=207 data-nosnippet>207</a> <span class="kw">let </span>start = <span class="self">self</span>.special.start_anchored_id;
<a href=#208 id=208 data-nosnippet>208</a> <span class="kw">if </span>start == DFA::DEAD {
<a href=#209 id=209 data-nosnippet>209</a> <span class="prelude-val">Err</span>(MatchError::invalid_input_anchored())
<a href=#210 id=210 data-nosnippet>210</a> } <span class="kw">else </span>{
<a href=#211 id=211 data-nosnippet>211</a> <span class="prelude-val">Ok</span>(start)
<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> }
<a href=#216 id=216 data-nosnippet>216</a>
<a href=#217 id=217 data-nosnippet>217</a> <span class="attr">#[inline(always)]
<a href=#218 id=218 data-nosnippet>218</a> </span><span class="kw">fn </span>next_state(
<a href=#219 id=219 data-nosnippet>219</a> <span class="kw-2">&amp;</span><span class="self">self</span>,
<a href=#220 id=220 data-nosnippet>220</a> _anchored: Anchored,
<a href=#221 id=221 data-nosnippet>221</a> sid: StateID,
<a href=#222 id=222 data-nosnippet>222</a> byte: u8,
<a href=#223 id=223 data-nosnippet>223</a> ) -&gt; StateID {
<a href=#224 id=224 data-nosnippet>224</a> <span class="kw">let </span>class = <span class="self">self</span>.byte_classes.get(byte);
<a href=#225 id=225 data-nosnippet>225</a> <span class="self">self</span>.trans[(sid.as_u32() + u32::from(class)).as_usize()]
<a href=#226 id=226 data-nosnippet>226</a> }
<a href=#227 id=227 data-nosnippet>227</a>
<a href=#228 id=228 data-nosnippet>228</a> <span class="attr">#[inline(always)]
<a href=#229 id=229 data-nosnippet>229</a> </span><span class="kw">fn </span>is_special(<span class="kw-2">&amp;</span><span class="self">self</span>, sid: StateID) -&gt; bool {
<a href=#230 id=230 data-nosnippet>230</a> sid &lt;= <span class="self">self</span>.special.max_special_id
<a href=#231 id=231 data-nosnippet>231</a> }
<a href=#232 id=232 data-nosnippet>232</a>
<a href=#233 id=233 data-nosnippet>233</a> <span class="attr">#[inline(always)]
<a href=#234 id=234 data-nosnippet>234</a> </span><span class="kw">fn </span>is_dead(<span class="kw-2">&amp;</span><span class="self">self</span>, sid: StateID) -&gt; bool {
<a href=#235 id=235 data-nosnippet>235</a> sid == DFA::DEAD
<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> <span class="attr">#[inline(always)]
<a href=#239 id=239 data-nosnippet>239</a> </span><span class="kw">fn </span>is_match(<span class="kw-2">&amp;</span><span class="self">self</span>, sid: StateID) -&gt; bool {
<a href=#240 id=240 data-nosnippet>240</a> !<span class="self">self</span>.is_dead(sid) &amp;&amp; sid &lt;= <span class="self">self</span>.special.max_match_id
<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> <span class="attr">#[inline(always)]
<a href=#244 id=244 data-nosnippet>244</a> </span><span class="kw">fn </span>is_start(<span class="kw-2">&amp;</span><span class="self">self</span>, sid: StateID) -&gt; bool {
<a href=#245 id=245 data-nosnippet>245</a> sid == <span class="self">self</span>.special.start_unanchored_id
<a href=#246 id=246 data-nosnippet>246</a> || sid == <span class="self">self</span>.special.start_anchored_id
<a href=#247 id=247 data-nosnippet>247</a> }
<a href=#248 id=248 data-nosnippet>248</a>
<a href=#249 id=249 data-nosnippet>249</a> <span class="attr">#[inline(always)]
<a href=#250 id=250 data-nosnippet>250</a> </span><span class="kw">fn </span>match_kind(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; MatchKind {
<a href=#251 id=251 data-nosnippet>251</a> <span class="self">self</span>.match_kind
<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> <span class="attr">#[inline(always)]
<a href=#255 id=255 data-nosnippet>255</a> </span><span class="kw">fn </span>patterns_len(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; usize {
<a href=#256 id=256 data-nosnippet>256</a> <span class="self">self</span>.pattern_lens.len()
<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="attr">#[inline(always)]
<a href=#260 id=260 data-nosnippet>260</a> </span><span class="kw">fn </span>pattern_len(<span class="kw-2">&amp;</span><span class="self">self</span>, pid: PatternID) -&gt; usize {
<a href=#261 id=261 data-nosnippet>261</a> <span class="self">self</span>.pattern_lens[pid].as_usize()
<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="attr">#[inline(always)]
<a href=#265 id=265 data-nosnippet>265</a> </span><span class="kw">fn </span>min_pattern_len(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; usize {
<a href=#266 id=266 data-nosnippet>266</a> <span class="self">self</span>.min_pattern_len
<a href=#267 id=267 data-nosnippet>267</a> }
<a href=#268 id=268 data-nosnippet>268</a>
<a href=#269 id=269 data-nosnippet>269</a> <span class="attr">#[inline(always)]
<a href=#270 id=270 data-nosnippet>270</a> </span><span class="kw">fn </span>max_pattern_len(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; usize {
<a href=#271 id=271 data-nosnippet>271</a> <span class="self">self</span>.max_pattern_len
<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="attr">#[inline(always)]
<a href=#275 id=275 data-nosnippet>275</a> </span><span class="kw">fn </span>match_len(<span class="kw-2">&amp;</span><span class="self">self</span>, sid: StateID) -&gt; usize {
<a href=#276 id=276 data-nosnippet>276</a> <span class="macro">debug_assert!</span>(<span class="self">self</span>.is_match(sid));
<a href=#277 id=277 data-nosnippet>277</a> <span class="kw">let </span>offset = (sid.as_usize() &gt;&gt; <span class="self">self</span>.stride2) - <span class="number">2</span>;
<a href=#278 id=278 data-nosnippet>278</a> <span class="self">self</span>.matches[offset].len()
<a href=#279 id=279 data-nosnippet>279</a> }
<a href=#280 id=280 data-nosnippet>280</a>
<a href=#281 id=281 data-nosnippet>281</a> <span class="attr">#[inline(always)]
<a href=#282 id=282 data-nosnippet>282</a> </span><span class="kw">fn </span>match_pattern(<span class="kw-2">&amp;</span><span class="self">self</span>, sid: StateID, index: usize) -&gt; PatternID {
<a href=#283 id=283 data-nosnippet>283</a> <span class="macro">debug_assert!</span>(<span class="self">self</span>.is_match(sid));
<a href=#284 id=284 data-nosnippet>284</a> <span class="kw">let </span>offset = (sid.as_usize() &gt;&gt; <span class="self">self</span>.stride2) - <span class="number">2</span>;
<a href=#285 id=285 data-nosnippet>285</a> <span class="self">self</span>.matches[offset][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> <span class="attr">#[inline(always)]
<a href=#289 id=289 data-nosnippet>289</a> </span><span class="kw">fn </span>memory_usage(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; usize {
<a href=#290 id=290 data-nosnippet>290</a> <span class="kw">use </span>core::mem::size_of;
<a href=#291 id=291 data-nosnippet>291</a>
<a href=#292 id=292 data-nosnippet>292</a> (<span class="self">self</span>.trans.len() * size_of::&lt;u32&gt;())
<a href=#293 id=293 data-nosnippet>293</a> + (<span class="self">self</span>.matches.len() * size_of::&lt;Vec&lt;PatternID&gt;&gt;())
<a href=#294 id=294 data-nosnippet>294</a> + <span class="self">self</span>.matches_memory_usage
<a href=#295 id=295 data-nosnippet>295</a> + (<span class="self">self</span>.pattern_lens.len() * size_of::&lt;SmallIndex&gt;())
<a href=#296 id=296 data-nosnippet>296</a> + <span class="self">self</span>.prefilter.as_ref().map_or(<span class="number">0</span>, |p| p.memory_usage())
<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">#[inline(always)]
<a href=#300 id=300 data-nosnippet>300</a> </span><span class="kw">fn </span>prefilter(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; <span class="prelude-ty">Option</span>&lt;<span class="kw-2">&amp;</span>Prefilter&gt; {
<a href=#301 id=301 data-nosnippet>301</a> <span class="self">self</span>.prefilter.as_ref()
<a href=#302 id=302 data-nosnippet>302</a> }
<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><span class="kw">impl </span>core::fmt::Debug <span class="kw">for </span>DFA {
<a href=#306 id=306 data-nosnippet>306</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=#307 id=307 data-nosnippet>307</a> <span class="kw">use crate</span>::{
<a href=#308 id=308 data-nosnippet>308</a> automaton::{fmt_state_indicator, sparse_transitions},
<a href=#309 id=309 data-nosnippet>309</a> util::debug::DebugByte,
<a href=#310 id=310 data-nosnippet>310</a> };
<a href=#311 id=311 data-nosnippet>311</a>
<a href=#312 id=312 data-nosnippet>312</a> <span class="macro">writeln!</span>(f, <span class="string">"dfa::DFA("</span>)<span class="question-mark">?</span>;
<a href=#313 id=313 data-nosnippet>313</a> <span class="kw">for </span>index <span class="kw">in </span><span class="number">0</span>..<span class="self">self</span>.state_len {
<a href=#314 id=314 data-nosnippet>314</a> <span class="kw">let </span>sid = StateID::new_unchecked(index &lt;&lt; <span class="self">self</span>.stride2);
<a href=#315 id=315 data-nosnippet>315</a> <span class="comment">// While we do currently include the FAIL state in the transition
<a href=#316 id=316 data-nosnippet>316</a> // table (to simplify construction), it is never actually used. It
<a href=#317 id=317 data-nosnippet>317</a> // poses problems with the code below because it gets treated as
<a href=#318 id=318 data-nosnippet>318</a> // a match state incidentally when it is, of course, not. So we
<a href=#319 id=319 data-nosnippet>319</a> // special case it. The fail state is always the first state after
<a href=#320 id=320 data-nosnippet>320</a> // the dead state.
<a href=#321 id=321 data-nosnippet>321</a> //
<a href=#322 id=322 data-nosnippet>322</a> // If the construction is changed to remove the fail state (it
<a href=#323 id=323 data-nosnippet>323</a> // probably should be), then this special case should be updated.
<a href=#324 id=324 data-nosnippet>324</a> </span><span class="kw">if </span>index == <span class="number">1 </span>{
<a href=#325 id=325 data-nosnippet>325</a> <span class="macro">writeln!</span>(f, <span class="string">"F {:06}:"</span>, sid.as_usize())<span class="question-mark">?</span>;
<a href=#326 id=326 data-nosnippet>326</a> <span class="kw">continue</span>;
<a href=#327 id=327 data-nosnippet>327</a> }
<a href=#328 id=328 data-nosnippet>328</a> fmt_state_indicator(f, <span class="self">self</span>, sid)<span class="question-mark">?</span>;
<a href=#329 id=329 data-nosnippet>329</a> <span class="macro">write!</span>(f, <span class="string">"{:06}: "</span>, sid.as_usize())<span class="question-mark">?</span>;
<a href=#330 id=330 data-nosnippet>330</a>
<a href=#331 id=331 data-nosnippet>331</a> <span class="kw">let </span>it = (<span class="number">0</span>..<span class="self">self</span>.byte_classes.alphabet_len()).map(|class| {
<a href=#332 id=332 data-nosnippet>332</a> (class.as_u8(), <span class="self">self</span>.trans[sid.as_usize() + class])
<a href=#333 id=333 data-nosnippet>333</a> });
<a href=#334 id=334 data-nosnippet>334</a> <span class="kw">for </span>(i, (start, end, next)) <span class="kw">in </span>sparse_transitions(it).enumerate() {
<a href=#335 id=335 data-nosnippet>335</a> <span class="kw">if </span>i &gt; <span class="number">0 </span>{
<a href=#336 id=336 data-nosnippet>336</a> <span class="macro">write!</span>(f, <span class="string">", "</span>)<span class="question-mark">?</span>;
<a href=#337 id=337 data-nosnippet>337</a> }
<a href=#338 id=338 data-nosnippet>338</a> <span class="kw">if </span>start == end {
<a href=#339 id=339 data-nosnippet>339</a> <span class="macro">write!</span>(
<a href=#340 id=340 data-nosnippet>340</a> f,
<a href=#341 id=341 data-nosnippet>341</a> <span class="string">"{:?} =&gt; {:?}"</span>,
<a href=#342 id=342 data-nosnippet>342</a> DebugByte(start),
<a href=#343 id=343 data-nosnippet>343</a> next.as_usize()
<a href=#344 id=344 data-nosnippet>344</a> )<span class="question-mark">?</span>;
<a href=#345 id=345 data-nosnippet>345</a> } <span class="kw">else </span>{
<a href=#346 id=346 data-nosnippet>346</a> <span class="macro">write!</span>(
<a href=#347 id=347 data-nosnippet>347</a> f,
<a href=#348 id=348 data-nosnippet>348</a> <span class="string">"{:?}-{:?} =&gt; {:?}"</span>,
<a href=#349 id=349 data-nosnippet>349</a> DebugByte(start),
<a href=#350 id=350 data-nosnippet>350</a> DebugByte(end),
<a href=#351 id=351 data-nosnippet>351</a> next.as_usize()
<a href=#352 id=352 data-nosnippet>352</a> )<span class="question-mark">?</span>;
<a href=#353 id=353 data-nosnippet>353</a> }
<a href=#354 id=354 data-nosnippet>354</a> }
<a href=#355 id=355 data-nosnippet>355</a> <span class="macro">write!</span>(f, <span class="string">"\n"</span>)<span class="question-mark">?</span>;
<a href=#356 id=356 data-nosnippet>356</a> <span class="kw">if </span><span class="self">self</span>.is_match(sid) {
<a href=#357 id=357 data-nosnippet>357</a> <span class="macro">write!</span>(f, <span class="string">" matches: "</span>)<span class="question-mark">?</span>;
<a href=#358 id=358 data-nosnippet>358</a> <span class="kw">for </span>i <span class="kw">in </span><span class="number">0</span>..<span class="self">self</span>.match_len(sid) {
<a href=#359 id=359 data-nosnippet>359</a> <span class="kw">if </span>i &gt; <span class="number">0 </span>{
<a href=#360 id=360 data-nosnippet>360</a> <span class="macro">write!</span>(f, <span class="string">", "</span>)<span class="question-mark">?</span>;
<a href=#361 id=361 data-nosnippet>361</a> }
<a href=#362 id=362 data-nosnippet>362</a> <span class="kw">let </span>pid = <span class="self">self</span>.match_pattern(sid, i);
<a href=#363 id=363 data-nosnippet>363</a> <span class="macro">write!</span>(f, <span class="string">"{}"</span>, pid.as_usize())<span class="question-mark">?</span>;
<a href=#364 id=364 data-nosnippet>364</a> }
<a href=#365 id=365 data-nosnippet>365</a> <span class="macro">write!</span>(f, <span class="string">"\n"</span>)<span class="question-mark">?</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="macro">writeln!</span>(f, <span class="string">"match kind: {:?}"</span>, <span class="self">self</span>.match_kind)<span class="question-mark">?</span>;
<a href=#369 id=369 data-nosnippet>369</a> <span class="macro">writeln!</span>(f, <span class="string">"prefilter: {:?}"</span>, <span class="self">self</span>.prefilter.is_some())<span class="question-mark">?</span>;
<a href=#370 id=370 data-nosnippet>370</a> <span class="macro">writeln!</span>(f, <span class="string">"state length: {:?}"</span>, <span class="self">self</span>.state_len)<span class="question-mark">?</span>;
<a href=#371 id=371 data-nosnippet>371</a> <span class="macro">writeln!</span>(f, <span class="string">"pattern length: {:?}"</span>, <span class="self">self</span>.patterns_len())<span class="question-mark">?</span>;
<a href=#372 id=372 data-nosnippet>372</a> <span class="macro">writeln!</span>(f, <span class="string">"shortest pattern length: {:?}"</span>, <span class="self">self</span>.min_pattern_len)<span class="question-mark">?</span>;
<a href=#373 id=373 data-nosnippet>373</a> <span class="macro">writeln!</span>(f, <span class="string">"longest pattern length: {:?}"</span>, <span class="self">self</span>.max_pattern_len)<span class="question-mark">?</span>;
<a href=#374 id=374 data-nosnippet>374</a> <span class="macro">writeln!</span>(f, <span class="string">"alphabet length: {:?}"</span>, <span class="self">self</span>.alphabet_len)<span class="question-mark">?</span>;
<a href=#375 id=375 data-nosnippet>375</a> <span class="macro">writeln!</span>(f, <span class="string">"stride: {:?}"</span>, <span class="number">1 </span>&lt;&lt; <span class="self">self</span>.stride2)<span class="question-mark">?</span>;
<a href=#376 id=376 data-nosnippet>376</a> <span class="macro">writeln!</span>(f, <span class="string">"byte classes: {:?}"</span>, <span class="self">self</span>.byte_classes)<span class="question-mark">?</span>;
<a href=#377 id=377 data-nosnippet>377</a> <span class="macro">writeln!</span>(f, <span class="string">"memory usage: {:?}"</span>, <span class="self">self</span>.memory_usage())<span class="question-mark">?</span>;
<a href=#378 id=378 data-nosnippet>378</a> <span class="macro">writeln!</span>(f, <span class="string">")"</span>)<span class="question-mark">?</span>;
<a href=#379 id=379 data-nosnippet>379</a> <span class="prelude-val">Ok</span>(())
<a href=#380 id=380 data-nosnippet>380</a> }
<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><span class="doccomment">/// A builder for configuring an Aho-Corasick DFA.
<a href=#384 id=384 data-nosnippet>384</a>///
<a href=#385 id=385 data-nosnippet>385</a>/// This builder has a subset of the options available to a
<a href=#386 id=386 data-nosnippet>386</a>/// [`AhoCorasickBuilder`](crate::AhoCorasickBuilder). Of the shared options,
<a href=#387 id=387 data-nosnippet>387</a>/// their behavior is identical.
<a href=#388 id=388 data-nosnippet>388</a></span><span class="attr">#[derive(Clone, Debug)]
<a href=#389 id=389 data-nosnippet>389</a></span><span class="kw">pub struct </span>Builder {
<a href=#390 id=390 data-nosnippet>390</a> noncontiguous: noncontiguous::Builder,
<a href=#391 id=391 data-nosnippet>391</a> start_kind: StartKind,
<a href=#392 id=392 data-nosnippet>392</a> byte_classes: bool,
<a href=#393 id=393 data-nosnippet>393</a>}
<a href=#394 id=394 data-nosnippet>394</a>
<a href=#395 id=395 data-nosnippet>395</a><span class="kw">impl </span>Default <span class="kw">for </span>Builder {
<a href=#396 id=396 data-nosnippet>396</a> <span class="kw">fn </span>default() -&gt; Builder {
<a href=#397 id=397 data-nosnippet>397</a> Builder {
<a href=#398 id=398 data-nosnippet>398</a> noncontiguous: noncontiguous::Builder::new(),
<a href=#399 id=399 data-nosnippet>399</a> start_kind: StartKind::Unanchored,
<a href=#400 id=400 data-nosnippet>400</a> byte_classes: <span class="bool-val">true</span>,
<a href=#401 id=401 data-nosnippet>401</a> }
<a href=#402 id=402 data-nosnippet>402</a> }
<a href=#403 id=403 data-nosnippet>403</a>}
<a href=#404 id=404 data-nosnippet>404</a>
<a href=#405 id=405 data-nosnippet>405</a><span class="kw">impl </span>Builder {
<a href=#406 id=406 data-nosnippet>406</a> <span class="doccomment">/// Create a new builder for configuring an Aho-Corasick DFA.
<a href=#407 id=407 data-nosnippet>407</a> </span><span class="kw">pub fn </span>new() -&gt; Builder {
<a href=#408 id=408 data-nosnippet>408</a> Builder::default()
<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> <span class="doccomment">/// Build an Aho-Corasick DFA from the given iterator of patterns.
<a href=#412 id=412 data-nosnippet>412</a> ///
<a href=#413 id=413 data-nosnippet>413</a> /// A builder may be reused to create more DFAs.
<a href=#414 id=414 data-nosnippet>414</a> </span><span class="kw">pub fn </span>build&lt;I, P&gt;(<span class="kw-2">&amp;</span><span class="self">self</span>, patterns: I) -&gt; <span class="prelude-ty">Result</span>&lt;DFA, BuildError&gt;
<a href=#415 id=415 data-nosnippet>415</a> <span class="kw">where
<a href=#416 id=416 data-nosnippet>416</a> </span>I: IntoIterator&lt;Item = P&gt;,
<a href=#417 id=417 data-nosnippet>417</a> P: AsRef&lt;[u8]&gt;,
<a href=#418 id=418 data-nosnippet>418</a> {
<a href=#419 id=419 data-nosnippet>419</a> <span class="kw">let </span>nnfa = <span class="self">self</span>.noncontiguous.build(patterns)<span class="question-mark">?</span>;
<a href=#420 id=420 data-nosnippet>420</a> <span class="self">self</span>.build_from_noncontiguous(<span class="kw-2">&amp;</span>nnfa)
<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">/// Build an Aho-Corasick DFA from the given noncontiguous NFA.
<a href=#424 id=424 data-nosnippet>424</a> ///
<a href=#425 id=425 data-nosnippet>425</a> /// Note that when this method is used, only the `start_kind` and
<a href=#426 id=426 data-nosnippet>426</a> /// `byte_classes` settings on this builder are respected. The other
<a href=#427 id=427 data-nosnippet>427</a> /// settings only apply to the initial construction of the Aho-Corasick
<a href=#428 id=428 data-nosnippet>428</a> /// automaton. Since using this method requires that initial construction
<a href=#429 id=429 data-nosnippet>429</a> /// has already completed, all settings impacting only initial construction
<a href=#430 id=430 data-nosnippet>430</a> /// are no longer relevant.
<a href=#431 id=431 data-nosnippet>431</a> </span><span class="kw">pub fn </span>build_from_noncontiguous(
<a href=#432 id=432 data-nosnippet>432</a> <span class="kw-2">&amp;</span><span class="self">self</span>,
<a href=#433 id=433 data-nosnippet>433</a> nnfa: <span class="kw-2">&amp;</span>noncontiguous::NFA,
<a href=#434 id=434 data-nosnippet>434</a> ) -&gt; <span class="prelude-ty">Result</span>&lt;DFA, BuildError&gt; {
<a href=#435 id=435 data-nosnippet>435</a> <span class="macro">debug!</span>(<span class="string">"building DFA"</span>);
<a href=#436 id=436 data-nosnippet>436</a> <span class="kw">let </span>byte_classes = <span class="kw">if </span><span class="self">self</span>.byte_classes {
<a href=#437 id=437 data-nosnippet>437</a> nnfa.byte_classes().clone()
<a href=#438 id=438 data-nosnippet>438</a> } <span class="kw">else </span>{
<a href=#439 id=439 data-nosnippet>439</a> ByteClasses::singletons()
<a href=#440 id=440 data-nosnippet>440</a> };
<a href=#441 id=441 data-nosnippet>441</a> <span class="kw">let </span>state_len = <span class="kw">match </span><span class="self">self</span>.start_kind {
<a href=#442 id=442 data-nosnippet>442</a> StartKind::Unanchored | StartKind::Anchored =&gt; nnfa.states().len(),
<a href=#443 id=443 data-nosnippet>443</a> StartKind::Both =&gt; {
<a href=#444 id=444 data-nosnippet>444</a> <span class="comment">// These unwraps are OK because we know that the number of
<a href=#445 id=445 data-nosnippet>445</a> // NFA states is &lt; StateID::LIMIT which is in turn less than
<a href=#446 id=446 data-nosnippet>446</a> // i32::MAX. Thus, there is always room to multiply by 2.
<a href=#447 id=447 data-nosnippet>447</a> // Finally, the number of states is always at least 4 in the
<a href=#448 id=448 data-nosnippet>448</a> // NFA (DEAD, FAIL, START-UNANCHORED, START-ANCHORED), so the
<a href=#449 id=449 data-nosnippet>449</a> // subtraction of 4 is okay.
<a href=#450 id=450 data-nosnippet>450</a> //
<a href=#451 id=451 data-nosnippet>451</a> // Note that we subtract 4 because the "anchored" part of
<a href=#452 id=452 data-nosnippet>452</a> // the DFA duplicates the unanchored part (without failure
<a href=#453 id=453 data-nosnippet>453</a> // transitions), but reuses the DEAD, FAIL and START states.
<a href=#454 id=454 data-nosnippet>454</a> </span>nnfa.states()
<a href=#455 id=455 data-nosnippet>455</a> .len()
<a href=#456 id=456 data-nosnippet>456</a> .checked_mul(<span class="number">2</span>)
<a href=#457 id=457 data-nosnippet>457</a> .unwrap()
<a href=#458 id=458 data-nosnippet>458</a> .checked_sub(<span class="number">4</span>)
<a href=#459 id=459 data-nosnippet>459</a> .unwrap()
<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="kw">let </span>trans_len =
<a href=#463 id=463 data-nosnippet>463</a> <span class="kw">match </span>state_len.checked_shl(byte_classes.stride2().as_u32()) {
<a href=#464 id=464 data-nosnippet>464</a> <span class="prelude-val">Some</span>(trans_len) =&gt; trans_len,
<a href=#465 id=465 data-nosnippet>465</a> <span class="prelude-val">None </span>=&gt; {
<a href=#466 id=466 data-nosnippet>466</a> <span class="kw">return </span><span class="prelude-val">Err</span>(BuildError::state_id_overflow(
<a href=#467 id=467 data-nosnippet>467</a> StateID::MAX.as_u64(),
<a href=#468 id=468 data-nosnippet>468</a> usize::MAX.as_u64(),
<a href=#469 id=469 data-nosnippet>469</a> ))
<a href=#470 id=470 data-nosnippet>470</a> }
<a href=#471 id=471 data-nosnippet>471</a> };
<a href=#472 id=472 data-nosnippet>472</a> StateID::new(trans_len.checked_sub(byte_classes.stride()).unwrap())
<a href=#473 id=473 data-nosnippet>473</a> .map_err(|e| {
<a href=#474 id=474 data-nosnippet>474</a> BuildError::state_id_overflow(
<a href=#475 id=475 data-nosnippet>475</a> StateID::MAX.as_u64(),
<a href=#476 id=476 data-nosnippet>476</a> e.attempted(),
<a href=#477 id=477 data-nosnippet>477</a> )
<a href=#478 id=478 data-nosnippet>478</a> })<span class="question-mark">?</span>;
<a href=#479 id=479 data-nosnippet>479</a> <span class="kw">let </span>num_match_states = <span class="kw">match </span><span class="self">self</span>.start_kind {
<a href=#480 id=480 data-nosnippet>480</a> StartKind::Unanchored | StartKind::Anchored =&gt; {
<a href=#481 id=481 data-nosnippet>481</a> nnfa.special().max_match_id.as_usize().checked_sub(<span class="number">1</span>).unwrap()
<a href=#482 id=482 data-nosnippet>482</a> }
<a href=#483 id=483 data-nosnippet>483</a> StartKind::Both =&gt; nnfa
<a href=#484 id=484 data-nosnippet>484</a> .special()
<a href=#485 id=485 data-nosnippet>485</a> .max_match_id
<a href=#486 id=486 data-nosnippet>486</a> .as_usize()
<a href=#487 id=487 data-nosnippet>487</a> .checked_sub(<span class="number">1</span>)
<a href=#488 id=488 data-nosnippet>488</a> .unwrap()
<a href=#489 id=489 data-nosnippet>489</a> .checked_mul(<span class="number">2</span>)
<a href=#490 id=490 data-nosnippet>490</a> .unwrap(),
<a href=#491 id=491 data-nosnippet>491</a> };
<a href=#492 id=492 data-nosnippet>492</a> <span class="kw">let </span><span class="kw-2">mut </span>dfa = DFA {
<a href=#493 id=493 data-nosnippet>493</a> trans: <span class="macro">vec!</span>[DFA::DEAD; trans_len],
<a href=#494 id=494 data-nosnippet>494</a> matches: <span class="macro">vec!</span>[<span class="macro">vec!</span>[]; num_match_states],
<a href=#495 id=495 data-nosnippet>495</a> matches_memory_usage: <span class="number">0</span>,
<a href=#496 id=496 data-nosnippet>496</a> pattern_lens: nnfa.pattern_lens_raw().to_vec(),
<a href=#497 id=497 data-nosnippet>497</a> prefilter: nnfa.prefilter().cloned(),
<a href=#498 id=498 data-nosnippet>498</a> match_kind: nnfa.match_kind(),
<a href=#499 id=499 data-nosnippet>499</a> state_len,
<a href=#500 id=500 data-nosnippet>500</a> alphabet_len: byte_classes.alphabet_len(),
<a href=#501 id=501 data-nosnippet>501</a> stride2: byte_classes.stride2(),
<a href=#502 id=502 data-nosnippet>502</a> byte_classes,
<a href=#503 id=503 data-nosnippet>503</a> min_pattern_len: nnfa.min_pattern_len(),
<a href=#504 id=504 data-nosnippet>504</a> max_pattern_len: nnfa.max_pattern_len(),
<a href=#505 id=505 data-nosnippet>505</a> <span class="comment">// The special state IDs are set later.
<a href=#506 id=506 data-nosnippet>506</a> </span>special: Special::zero(),
<a href=#507 id=507 data-nosnippet>507</a> };
<a href=#508 id=508 data-nosnippet>508</a> <span class="kw">match </span><span class="self">self</span>.start_kind {
<a href=#509 id=509 data-nosnippet>509</a> StartKind::Both =&gt; {
<a href=#510 id=510 data-nosnippet>510</a> <span class="self">self</span>.finish_build_both_starts(nnfa, <span class="kw-2">&amp;mut </span>dfa);
<a href=#511 id=511 data-nosnippet>511</a> }
<a href=#512 id=512 data-nosnippet>512</a> StartKind::Unanchored =&gt; {
<a href=#513 id=513 data-nosnippet>513</a> <span class="self">self</span>.finish_build_one_start(Anchored::No, nnfa, <span class="kw-2">&amp;mut </span>dfa);
<a href=#514 id=514 data-nosnippet>514</a> }
<a href=#515 id=515 data-nosnippet>515</a> StartKind::Anchored =&gt; {
<a href=#516 id=516 data-nosnippet>516</a> <span class="self">self</span>.finish_build_one_start(Anchored::Yes, nnfa, <span class="kw-2">&amp;mut </span>dfa)
<a href=#517 id=517 data-nosnippet>517</a> }
<a href=#518 id=518 data-nosnippet>518</a> }
<a href=#519 id=519 data-nosnippet>519</a> <span class="macro">debug!</span>(
<a href=#520 id=520 data-nosnippet>520</a> <span class="string">"DFA built, &lt;states: {:?}, size: {:?}, \
<a href=#521 id=521 data-nosnippet>521</a> alphabet len: {:?}, stride: {:?}&gt;"</span>,
<a href=#522 id=522 data-nosnippet>522</a> dfa.state_len,
<a href=#523 id=523 data-nosnippet>523</a> dfa.memory_usage(),
<a href=#524 id=524 data-nosnippet>524</a> dfa.byte_classes.alphabet_len(),
<a href=#525 id=525 data-nosnippet>525</a> dfa.byte_classes.stride(),
<a href=#526 id=526 data-nosnippet>526</a> );
<a href=#527 id=527 data-nosnippet>527</a> <span class="comment">// The vectors can grow ~twice as big during construction because a
<a href=#528 id=528 data-nosnippet>528</a> // Vec amortizes growth. But here, let's shrink things back down to
<a href=#529 id=529 data-nosnippet>529</a> // what we actually need since we're never going to add more to it.
<a href=#530 id=530 data-nosnippet>530</a> </span>dfa.trans.shrink_to_fit();
<a href=#531 id=531 data-nosnippet>531</a> dfa.pattern_lens.shrink_to_fit();
<a href=#532 id=532 data-nosnippet>532</a> dfa.matches.shrink_to_fit();
<a href=#533 id=533 data-nosnippet>533</a> <span class="comment">// TODO: We might also want to shrink each Vec inside of `dfa.matches`,
<a href=#534 id=534 data-nosnippet>534</a> // or even better, convert it to one contiguous allocation. But I think
<a href=#535 id=535 data-nosnippet>535</a> // I went with nested allocs for good reason (can't remember), so this
<a href=#536 id=536 data-nosnippet>536</a> // may be tricky to do. I decided not to shrink them here because it
<a href=#537 id=537 data-nosnippet>537</a> // might require a fair bit of work to do. It's unclear whether it's
<a href=#538 id=538 data-nosnippet>538</a> // worth it.
<a href=#539 id=539 data-nosnippet>539</a> </span><span class="prelude-val">Ok</span>(dfa)
<a href=#540 id=540 data-nosnippet>540</a> }
<a href=#541 id=541 data-nosnippet>541</a>
<a href=#542 id=542 data-nosnippet>542</a> <span class="doccomment">/// Finishes building a DFA for either unanchored or anchored searches,
<a href=#543 id=543 data-nosnippet>543</a> /// but NOT both.
<a href=#544 id=544 data-nosnippet>544</a> </span><span class="kw">fn </span>finish_build_one_start(
<a href=#545 id=545 data-nosnippet>545</a> <span class="kw-2">&amp;</span><span class="self">self</span>,
<a href=#546 id=546 data-nosnippet>546</a> anchored: Anchored,
<a href=#547 id=547 data-nosnippet>547</a> nnfa: <span class="kw-2">&amp;</span>noncontiguous::NFA,
<a href=#548 id=548 data-nosnippet>548</a> dfa: <span class="kw-2">&amp;mut </span>DFA,
<a href=#549 id=549 data-nosnippet>549</a> ) {
<a href=#550 id=550 data-nosnippet>550</a> <span class="comment">// This function always succeeds because we check above that all of the
<a href=#551 id=551 data-nosnippet>551</a> // states in the NFA can be mapped to DFA state IDs.
<a href=#552 id=552 data-nosnippet>552</a> </span><span class="kw">let </span>stride2 = dfa.stride2;
<a href=#553 id=553 data-nosnippet>553</a> <span class="kw">let </span>old2new = |oldsid: StateID| {
<a href=#554 id=554 data-nosnippet>554</a> StateID::new_unchecked(oldsid.as_usize() &lt;&lt; stride2)
<a href=#555 id=555 data-nosnippet>555</a> };
<a href=#556 id=556 data-nosnippet>556</a> <span class="kw">for </span>(oldsid, state) <span class="kw">in </span>nnfa.states().iter().with_state_ids() {
<a href=#557 id=557 data-nosnippet>557</a> <span class="kw">let </span>newsid = old2new(oldsid);
<a href=#558 id=558 data-nosnippet>558</a> <span class="kw">if </span>state.is_match() {
<a href=#559 id=559 data-nosnippet>559</a> dfa.set_matches(newsid, nnfa.iter_matches(oldsid));
<a href=#560 id=560 data-nosnippet>560</a> }
<a href=#561 id=561 data-nosnippet>561</a> sparse_iter(
<a href=#562 id=562 data-nosnippet>562</a> nnfa,
<a href=#563 id=563 data-nosnippet>563</a> oldsid,
<a href=#564 id=564 data-nosnippet>564</a> <span class="kw-2">&amp;</span>dfa.byte_classes,
<a href=#565 id=565 data-nosnippet>565</a> |byte, class, <span class="kw-2">mut </span>oldnextsid| {
<a href=#566 id=566 data-nosnippet>566</a> <span class="kw">if </span>oldnextsid == noncontiguous::NFA::FAIL {
<a href=#567 id=567 data-nosnippet>567</a> <span class="kw">if </span>anchored.is_anchored() {
<a href=#568 id=568 data-nosnippet>568</a> oldnextsid = noncontiguous::NFA::DEAD;
<a href=#569 id=569 data-nosnippet>569</a> } <span class="kw">else if </span>state.fail() == noncontiguous::NFA::DEAD {
<a href=#570 id=570 data-nosnippet>570</a> <span class="comment">// This is a special case that avoids following
<a href=#571 id=571 data-nosnippet>571</a> // DEAD transitions in a non-contiguous NFA.
<a href=#572 id=572 data-nosnippet>572</a> // Following these transitions is pretty slow
<a href=#573 id=573 data-nosnippet>573</a> // because the non-contiguous NFA will always use
<a href=#574 id=574 data-nosnippet>574</a> // a sparse representation for it (because the
<a href=#575 id=575 data-nosnippet>575</a> // DEAD state is usually treated as a sentinel).
<a href=#576 id=576 data-nosnippet>576</a> // The *vast* majority of failure states are DEAD
<a href=#577 id=577 data-nosnippet>577</a> // states, so this winds up being pretty slow if
<a href=#578 id=578 data-nosnippet>578</a> // we go through the non-contiguous NFA state
<a href=#579 id=579 data-nosnippet>579</a> // transition logic. Instead, just do it ourselves.
<a href=#580 id=580 data-nosnippet>580</a> </span>oldnextsid = noncontiguous::NFA::DEAD;
<a href=#581 id=581 data-nosnippet>581</a> } <span class="kw">else </span>{
<a href=#582 id=582 data-nosnippet>582</a> oldnextsid = nnfa.next_state(
<a href=#583 id=583 data-nosnippet>583</a> Anchored::No,
<a href=#584 id=584 data-nosnippet>584</a> state.fail(),
<a href=#585 id=585 data-nosnippet>585</a> byte,
<a href=#586 id=586 data-nosnippet>586</a> );
<a href=#587 id=587 data-nosnippet>587</a> }
<a href=#588 id=588 data-nosnippet>588</a> }
<a href=#589 id=589 data-nosnippet>589</a> dfa.trans[newsid.as_usize() + usize::from(class)] =
<a href=#590 id=590 data-nosnippet>590</a> old2new(oldnextsid);
<a href=#591 id=591 data-nosnippet>591</a> },
<a href=#592 id=592 data-nosnippet>592</a> );
<a href=#593 id=593 data-nosnippet>593</a> }
<a href=#594 id=594 data-nosnippet>594</a> <span class="comment">// Now that we've remapped all the IDs in our states, all that's left
<a href=#595 id=595 data-nosnippet>595</a> // is remapping the special state IDs.
<a href=#596 id=596 data-nosnippet>596</a> </span><span class="kw">let </span>old = nnfa.special();
<a href=#597 id=597 data-nosnippet>597</a> <span class="kw">let </span>new = <span class="kw-2">&amp;mut </span>dfa.special;
<a href=#598 id=598 data-nosnippet>598</a> new.max_special_id = old2new(old.max_special_id);
<a href=#599 id=599 data-nosnippet>599</a> new.max_match_id = old2new(old.max_match_id);
<a href=#600 id=600 data-nosnippet>600</a> <span class="kw">if </span>anchored.is_anchored() {
<a href=#601 id=601 data-nosnippet>601</a> new.start_unanchored_id = DFA::DEAD;
<a href=#602 id=602 data-nosnippet>602</a> new.start_anchored_id = old2new(old.start_anchored_id);
<a href=#603 id=603 data-nosnippet>603</a> } <span class="kw">else </span>{
<a href=#604 id=604 data-nosnippet>604</a> new.start_unanchored_id = old2new(old.start_unanchored_id);
<a href=#605 id=605 data-nosnippet>605</a> new.start_anchored_id = DFA::DEAD;
<a href=#606 id=606 data-nosnippet>606</a> }
<a href=#607 id=607 data-nosnippet>607</a> }
<a href=#608 id=608 data-nosnippet>608</a>
<a href=#609 id=609 data-nosnippet>609</a> <span class="doccomment">/// Finishes building a DFA that supports BOTH unanchored and anchored
<a href=#610 id=610 data-nosnippet>610</a> /// searches. It works by inter-leaving unanchored states with anchored
<a href=#611 id=611 data-nosnippet>611</a> /// states in the same transition table. This way, we avoid needing to
<a href=#612 id=612 data-nosnippet>612</a> /// re-shuffle states afterward to ensure that our states still look like
<a href=#613 id=613 data-nosnippet>613</a> /// DEAD, MATCH, ..., START-UNANCHORED, START-ANCHORED, NON-MATCH, ...
<a href=#614 id=614 data-nosnippet>614</a> ///
<a href=#615 id=615 data-nosnippet>615</a> /// Honestly this is pretty inscrutable... Simplifications are most
<a href=#616 id=616 data-nosnippet>616</a> /// welcome.
<a href=#617 id=617 data-nosnippet>617</a> </span><span class="kw">fn </span>finish_build_both_starts(
<a href=#618 id=618 data-nosnippet>618</a> <span class="kw-2">&amp;</span><span class="self">self</span>,
<a href=#619 id=619 data-nosnippet>619</a> nnfa: <span class="kw-2">&amp;</span>noncontiguous::NFA,
<a href=#620 id=620 data-nosnippet>620</a> dfa: <span class="kw-2">&amp;mut </span>DFA,
<a href=#621 id=621 data-nosnippet>621</a> ) {
<a href=#622 id=622 data-nosnippet>622</a> <span class="kw">let </span>stride2 = dfa.stride2;
<a href=#623 id=623 data-nosnippet>623</a> <span class="kw">let </span>stride = <span class="number">1 </span>&lt;&lt; stride2;
<a href=#624 id=624 data-nosnippet>624</a> <span class="kw">let </span><span class="kw-2">mut </span>remap_unanchored = <span class="macro">vec!</span>[DFA::DEAD; nnfa.states().len()];
<a href=#625 id=625 data-nosnippet>625</a> <span class="kw">let </span><span class="kw-2">mut </span>remap_anchored = <span class="macro">vec!</span>[DFA::DEAD; nnfa.states().len()];
<a href=#626 id=626 data-nosnippet>626</a> <span class="kw">let </span><span class="kw-2">mut </span>is_anchored = <span class="macro">vec!</span>[<span class="bool-val">false</span>; dfa.state_len];
<a href=#627 id=627 data-nosnippet>627</a> <span class="kw">let </span><span class="kw-2">mut </span>newsid = DFA::DEAD;
<a href=#628 id=628 data-nosnippet>628</a> <span class="kw">let </span>next_dfa_id =
<a href=#629 id=629 data-nosnippet>629</a> |sid: StateID| StateID::new_unchecked(sid.as_usize() + stride);
<a href=#630 id=630 data-nosnippet>630</a> <span class="kw">for </span>(oldsid, state) <span class="kw">in </span>nnfa.states().iter().with_state_ids() {
<a href=#631 id=631 data-nosnippet>631</a> <span class="kw">if </span>oldsid == noncontiguous::NFA::DEAD
<a href=#632 id=632 data-nosnippet>632</a> || oldsid == noncontiguous::NFA::FAIL
<a href=#633 id=633 data-nosnippet>633</a> {
<a href=#634 id=634 data-nosnippet>634</a> remap_unanchored[oldsid] = newsid;
<a href=#635 id=635 data-nosnippet>635</a> remap_anchored[oldsid] = newsid;
<a href=#636 id=636 data-nosnippet>636</a> newsid = next_dfa_id(newsid);
<a href=#637 id=637 data-nosnippet>637</a> } <span class="kw">else if </span>oldsid == nnfa.special().start_unanchored_id
<a href=#638 id=638 data-nosnippet>638</a> || oldsid == nnfa.special().start_anchored_id
<a href=#639 id=639 data-nosnippet>639</a> {
<a href=#640 id=640 data-nosnippet>640</a> <span class="kw">if </span>oldsid == nnfa.special().start_unanchored_id {
<a href=#641 id=641 data-nosnippet>641</a> remap_unanchored[oldsid] = newsid;
<a href=#642 id=642 data-nosnippet>642</a> remap_anchored[oldsid] = DFA::DEAD;
<a href=#643 id=643 data-nosnippet>643</a> } <span class="kw">else </span>{
<a href=#644 id=644 data-nosnippet>644</a> remap_unanchored[oldsid] = DFA::DEAD;
<a href=#645 id=645 data-nosnippet>645</a> remap_anchored[oldsid] = newsid;
<a href=#646 id=646 data-nosnippet>646</a> is_anchored[newsid.as_usize() &gt;&gt; stride2] = <span class="bool-val">true</span>;
<a href=#647 id=647 data-nosnippet>647</a> }
<a href=#648 id=648 data-nosnippet>648</a> <span class="kw">if </span>state.is_match() {
<a href=#649 id=649 data-nosnippet>649</a> dfa.set_matches(newsid, nnfa.iter_matches(oldsid));
<a href=#650 id=650 data-nosnippet>650</a> }
<a href=#651 id=651 data-nosnippet>651</a> sparse_iter(
<a href=#652 id=652 data-nosnippet>652</a> nnfa,
<a href=#653 id=653 data-nosnippet>653</a> oldsid,
<a href=#654 id=654 data-nosnippet>654</a> <span class="kw-2">&amp;</span>dfa.byte_classes,
<a href=#655 id=655 data-nosnippet>655</a> |<span class="kw">_</span>, class, oldnextsid| {
<a href=#656 id=656 data-nosnippet>656</a> <span class="kw">let </span>class = usize::from(class);
<a href=#657 id=657 data-nosnippet>657</a> <span class="kw">if </span>oldnextsid == noncontiguous::NFA::FAIL {
<a href=#658 id=658 data-nosnippet>658</a> dfa.trans[newsid.as_usize() + class] = DFA::DEAD;
<a href=#659 id=659 data-nosnippet>659</a> } <span class="kw">else </span>{
<a href=#660 id=660 data-nosnippet>660</a> dfa.trans[newsid.as_usize() + class] = oldnextsid;
<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> newsid = next_dfa_id(newsid);
<a href=#665 id=665 data-nosnippet>665</a> } <span class="kw">else </span>{
<a href=#666 id=666 data-nosnippet>666</a> <span class="kw">let </span>unewsid = newsid;
<a href=#667 id=667 data-nosnippet>667</a> newsid = next_dfa_id(newsid);
<a href=#668 id=668 data-nosnippet>668</a> <span class="kw">let </span>anewsid = newsid;
<a href=#669 id=669 data-nosnippet>669</a> newsid = next_dfa_id(newsid);
<a href=#670 id=670 data-nosnippet>670</a>
<a href=#671 id=671 data-nosnippet>671</a> remap_unanchored[oldsid] = unewsid;
<a href=#672 id=672 data-nosnippet>672</a> remap_anchored[oldsid] = anewsid;
<a href=#673 id=673 data-nosnippet>673</a> is_anchored[anewsid.as_usize() &gt;&gt; stride2] = <span class="bool-val">true</span>;
<a href=#674 id=674 data-nosnippet>674</a> <span class="kw">if </span>state.is_match() {
<a href=#675 id=675 data-nosnippet>675</a> dfa.set_matches(unewsid, nnfa.iter_matches(oldsid));
<a href=#676 id=676 data-nosnippet>676</a> dfa.set_matches(anewsid, nnfa.iter_matches(oldsid));
<a href=#677 id=677 data-nosnippet>677</a> }
<a href=#678 id=678 data-nosnippet>678</a> sparse_iter(
<a href=#679 id=679 data-nosnippet>679</a> nnfa,
<a href=#680 id=680 data-nosnippet>680</a> oldsid,
<a href=#681 id=681 data-nosnippet>681</a> <span class="kw-2">&amp;</span>dfa.byte_classes,
<a href=#682 id=682 data-nosnippet>682</a> |byte, class, oldnextsid| {
<a href=#683 id=683 data-nosnippet>683</a> <span class="kw">let </span>class = usize::from(class);
<a href=#684 id=684 data-nosnippet>684</a> <span class="kw">if </span>oldnextsid == noncontiguous::NFA::FAIL {
<a href=#685 id=685 data-nosnippet>685</a> <span class="kw">let </span>oldnextsid =
<a href=#686 id=686 data-nosnippet>686</a> <span class="kw">if </span>state.fail() == noncontiguous::NFA::DEAD {
<a href=#687 id=687 data-nosnippet>687</a> noncontiguous::NFA::DEAD
<a href=#688 id=688 data-nosnippet>688</a> } <span class="kw">else </span>{
<a href=#689 id=689 data-nosnippet>689</a> nnfa.next_state(
<a href=#690 id=690 data-nosnippet>690</a> Anchored::No,
<a href=#691 id=691 data-nosnippet>691</a> state.fail(),
<a href=#692 id=692 data-nosnippet>692</a> byte,
<a href=#693 id=693 data-nosnippet>693</a> )
<a href=#694 id=694 data-nosnippet>694</a> };
<a href=#695 id=695 data-nosnippet>695</a> dfa.trans[unewsid.as_usize() + class] = oldnextsid;
<a href=#696 id=696 data-nosnippet>696</a> } <span class="kw">else </span>{
<a href=#697 id=697 data-nosnippet>697</a> dfa.trans[unewsid.as_usize() + class] = oldnextsid;
<a href=#698 id=698 data-nosnippet>698</a> dfa.trans[anewsid.as_usize() + class] = oldnextsid;
<a href=#699 id=699 data-nosnippet>699</a> }
<a href=#700 id=700 data-nosnippet>700</a> },
<a href=#701 id=701 data-nosnippet>701</a> );
<a href=#702 id=702 data-nosnippet>702</a> }
<a href=#703 id=703 data-nosnippet>703</a> }
<a href=#704 id=704 data-nosnippet>704</a> <span class="kw">for </span>i <span class="kw">in </span><span class="number">0</span>..dfa.state_len {
<a href=#705 id=705 data-nosnippet>705</a> <span class="kw">let </span>sid = i &lt;&lt; stride2;
<a href=#706 id=706 data-nosnippet>706</a> <span class="kw">if </span>is_anchored[i] {
<a href=#707 id=707 data-nosnippet>707</a> <span class="kw">for </span>next <span class="kw">in </span>dfa.trans[sid..][..stride].iter_mut() {
<a href=#708 id=708 data-nosnippet>708</a> <span class="kw-2">*</span>next = remap_anchored[<span class="kw-2">*</span>next];
<a href=#709 id=709 data-nosnippet>709</a> }
<a href=#710 id=710 data-nosnippet>710</a> } <span class="kw">else </span>{
<a href=#711 id=711 data-nosnippet>711</a> <span class="kw">for </span>next <span class="kw">in </span>dfa.trans[sid..][..stride].iter_mut() {
<a href=#712 id=712 data-nosnippet>712</a> <span class="kw-2">*</span>next = remap_unanchored[<span class="kw-2">*</span>next];
<a href=#713 id=713 data-nosnippet>713</a> }
<a href=#714 id=714 data-nosnippet>714</a> }
<a href=#715 id=715 data-nosnippet>715</a> }
<a href=#716 id=716 data-nosnippet>716</a> <span class="comment">// Now that we've remapped all the IDs in our states, all that's left
<a href=#717 id=717 data-nosnippet>717</a> // is remapping the special state IDs.
<a href=#718 id=718 data-nosnippet>718</a> </span><span class="kw">let </span>old = nnfa.special();
<a href=#719 id=719 data-nosnippet>719</a> <span class="kw">let </span>new = <span class="kw-2">&amp;mut </span>dfa.special;
<a href=#720 id=720 data-nosnippet>720</a> new.max_special_id = remap_anchored[old.max_special_id];
<a href=#721 id=721 data-nosnippet>721</a> new.max_match_id = remap_anchored[old.max_match_id];
<a href=#722 id=722 data-nosnippet>722</a> new.start_unanchored_id = remap_unanchored[old.start_unanchored_id];
<a href=#723 id=723 data-nosnippet>723</a> new.start_anchored_id = remap_anchored[old.start_anchored_id];
<a href=#724 id=724 data-nosnippet>724</a> }
<a href=#725 id=725 data-nosnippet>725</a>
<a href=#726 id=726 data-nosnippet>726</a> <span class="doccomment">/// Set the desired match semantics.
<a href=#727 id=727 data-nosnippet>727</a> ///
<a href=#728 id=728 data-nosnippet>728</a> /// This only applies when using [`Builder::build`] and not
<a href=#729 id=729 data-nosnippet>729</a> /// [`Builder::build_from_noncontiguous`].
<a href=#730 id=730 data-nosnippet>730</a> ///
<a href=#731 id=731 data-nosnippet>731</a> /// See
<a href=#732 id=732 data-nosnippet>732</a> /// [`AhoCorasickBuilder::match_kind`](crate::AhoCorasickBuilder::match_kind)
<a href=#733 id=733 data-nosnippet>733</a> /// for more documentation and examples.
<a href=#734 id=734 data-nosnippet>734</a> </span><span class="kw">pub fn </span>match_kind(<span class="kw-2">&amp;mut </span><span class="self">self</span>, kind: MatchKind) -&gt; <span class="kw-2">&amp;mut </span>Builder {
<a href=#735 id=735 data-nosnippet>735</a> <span class="self">self</span>.noncontiguous.match_kind(kind);
<a href=#736 id=736 data-nosnippet>736</a> <span class="self">self
<a href=#737 id=737 data-nosnippet>737</a> </span>}
<a href=#738 id=738 data-nosnippet>738</a>
<a href=#739 id=739 data-nosnippet>739</a> <span class="doccomment">/// Enable ASCII-aware case insensitive matching.
<a href=#740 id=740 data-nosnippet>740</a> ///
<a href=#741 id=741 data-nosnippet>741</a> /// This only applies when using [`Builder::build`] and not
<a href=#742 id=742 data-nosnippet>742</a> /// [`Builder::build_from_noncontiguous`].
<a href=#743 id=743 data-nosnippet>743</a> ///
<a href=#744 id=744 data-nosnippet>744</a> /// See
<a href=#745 id=745 data-nosnippet>745</a> /// [`AhoCorasickBuilder::ascii_case_insensitive`](crate::AhoCorasickBuilder::ascii_case_insensitive)
<a href=#746 id=746 data-nosnippet>746</a> /// for more documentation and examples.
<a href=#747 id=747 data-nosnippet>747</a> </span><span class="kw">pub fn </span>ascii_case_insensitive(<span class="kw-2">&amp;mut </span><span class="self">self</span>, yes: bool) -&gt; <span class="kw-2">&amp;mut </span>Builder {
<a href=#748 id=748 data-nosnippet>748</a> <span class="self">self</span>.noncontiguous.ascii_case_insensitive(yes);
<a href=#749 id=749 data-nosnippet>749</a> <span class="self">self
<a href=#750 id=750 data-nosnippet>750</a> </span>}
<a href=#751 id=751 data-nosnippet>751</a>
<a href=#752 id=752 data-nosnippet>752</a> <span class="doccomment">/// Enable heuristic prefilter optimizations.
<a href=#753 id=753 data-nosnippet>753</a> ///
<a href=#754 id=754 data-nosnippet>754</a> /// This only applies when using [`Builder::build`] and not
<a href=#755 id=755 data-nosnippet>755</a> /// [`Builder::build_from_noncontiguous`].
<a href=#756 id=756 data-nosnippet>756</a> ///
<a href=#757 id=757 data-nosnippet>757</a> /// See
<a href=#758 id=758 data-nosnippet>758</a> /// [`AhoCorasickBuilder::prefilter`](crate::AhoCorasickBuilder::prefilter)
<a href=#759 id=759 data-nosnippet>759</a> /// for more documentation and examples.
<a href=#760 id=760 data-nosnippet>760</a> </span><span class="kw">pub fn </span>prefilter(<span class="kw-2">&amp;mut </span><span class="self">self</span>, yes: bool) -&gt; <span class="kw-2">&amp;mut </span>Builder {
<a href=#761 id=761 data-nosnippet>761</a> <span class="self">self</span>.noncontiguous.prefilter(yes);
<a href=#762 id=762 data-nosnippet>762</a> <span class="self">self
<a href=#763 id=763 data-nosnippet>763</a> </span>}
<a href=#764 id=764 data-nosnippet>764</a>
<a href=#765 id=765 data-nosnippet>765</a> <span class="doccomment">/// Sets the starting state configuration for the automaton.
<a href=#766 id=766 data-nosnippet>766</a> ///
<a href=#767 id=767 data-nosnippet>767</a> /// See
<a href=#768 id=768 data-nosnippet>768</a> /// [`AhoCorasickBuilder::start_kind`](crate::AhoCorasickBuilder::start_kind)
<a href=#769 id=769 data-nosnippet>769</a> /// for more documentation and examples.
<a href=#770 id=770 data-nosnippet>770</a> </span><span class="kw">pub fn </span>start_kind(<span class="kw-2">&amp;mut </span><span class="self">self</span>, kind: StartKind) -&gt; <span class="kw-2">&amp;mut </span>Builder {
<a href=#771 id=771 data-nosnippet>771</a> <span class="self">self</span>.start_kind = kind;
<a href=#772 id=772 data-nosnippet>772</a> <span class="self">self
<a href=#773 id=773 data-nosnippet>773</a> </span>}
<a href=#774 id=774 data-nosnippet>774</a>
<a href=#775 id=775 data-nosnippet>775</a> <span class="doccomment">/// A debug setting for whether to attempt to shrink the size of the
<a href=#776 id=776 data-nosnippet>776</a> /// automaton's alphabet or not.
<a href=#777 id=777 data-nosnippet>777</a> ///
<a href=#778 id=778 data-nosnippet>778</a> /// This should never be enabled unless you're debugging an automaton.
<a href=#779 id=779 data-nosnippet>779</a> /// Namely, disabling byte classes makes transitions easier to reason
<a href=#780 id=780 data-nosnippet>780</a> /// about, since they use the actual bytes instead of equivalence classes.
<a href=#781 id=781 data-nosnippet>781</a> /// Disabling this confers no performance benefit at search time.
<a href=#782 id=782 data-nosnippet>782</a> ///
<a href=#783 id=783 data-nosnippet>783</a> /// See
<a href=#784 id=784 data-nosnippet>784</a> /// [`AhoCorasickBuilder::byte_classes`](crate::AhoCorasickBuilder::byte_classes)
<a href=#785 id=785 data-nosnippet>785</a> /// for more documentation and examples.
<a href=#786 id=786 data-nosnippet>786</a> </span><span class="kw">pub fn </span>byte_classes(<span class="kw-2">&amp;mut </span><span class="self">self</span>, yes: bool) -&gt; <span class="kw-2">&amp;mut </span>Builder {
<a href=#787 id=787 data-nosnippet>787</a> <span class="self">self</span>.byte_classes = yes;
<a href=#788 id=788 data-nosnippet>788</a> <span class="self">self
<a href=#789 id=789 data-nosnippet>789</a> </span>}
<a href=#790 id=790 data-nosnippet>790</a>}
<a href=#791 id=791 data-nosnippet>791</a>
<a href=#792 id=792 data-nosnippet>792</a><span class="doccomment">/// Iterate over all possible equivalence class transitions in this state.
<a href=#793 id=793 data-nosnippet>793</a>/// The closure is called for all transitions with a distinct equivalence
<a href=#794 id=794 data-nosnippet>794</a>/// class, even those not explicitly represented in this sparse state. For
<a href=#795 id=795 data-nosnippet>795</a>/// any implicitly defined transitions, the given closure is called with
<a href=#796 id=796 data-nosnippet>796</a>/// the fail state ID.
<a href=#797 id=797 data-nosnippet>797</a>///
<a href=#798 id=798 data-nosnippet>798</a>/// The closure is guaranteed to be called precisely
<a href=#799 id=799 data-nosnippet>799</a>/// `byte_classes.alphabet_len()` times, once for every possible class in
<a href=#800 id=800 data-nosnippet>800</a>/// ascending order.
<a href=#801 id=801 data-nosnippet>801</a></span><span class="kw">fn </span>sparse_iter&lt;F: FnMut(u8, u8, StateID)&gt;(
<a href=#802 id=802 data-nosnippet>802</a> nnfa: <span class="kw-2">&amp;</span>noncontiguous::NFA,
<a href=#803 id=803 data-nosnippet>803</a> oldsid: StateID,
<a href=#804 id=804 data-nosnippet>804</a> classes: <span class="kw-2">&amp;</span>ByteClasses,
<a href=#805 id=805 data-nosnippet>805</a> <span class="kw-2">mut </span>f: F,
<a href=#806 id=806 data-nosnippet>806</a>) {
<a href=#807 id=807 data-nosnippet>807</a> <span class="kw">let </span><span class="kw-2">mut </span>prev_class = <span class="prelude-val">None</span>;
<a href=#808 id=808 data-nosnippet>808</a> <span class="kw">let </span><span class="kw-2">mut </span>byte = <span class="number">0usize</span>;
<a href=#809 id=809 data-nosnippet>809</a> <span class="kw">for </span>t <span class="kw">in </span>nnfa.iter_trans(oldsid) {
<a href=#810 id=810 data-nosnippet>810</a> <span class="kw">while </span>byte &lt; usize::from(t.byte()) {
<a href=#811 id=811 data-nosnippet>811</a> <span class="kw">let </span>rep = byte.as_u8();
<a href=#812 id=812 data-nosnippet>812</a> <span class="kw">let </span>class = classes.get(rep);
<a href=#813 id=813 data-nosnippet>813</a> byte += <span class="number">1</span>;
<a href=#814 id=814 data-nosnippet>814</a> <span class="kw">if </span><span class="macro">prev_class !</span>= <span class="prelude-val">Some</span>(class) {
<a href=#815 id=815 data-nosnippet>815</a> f(rep, class, noncontiguous::NFA::FAIL);
<a href=#816 id=816 data-nosnippet>816</a> prev_class = <span class="prelude-val">Some</span>(class);
<a href=#817 id=817 data-nosnippet>817</a> }
<a href=#818 id=818 data-nosnippet>818</a> }
<a href=#819 id=819 data-nosnippet>819</a> <span class="kw">let </span>rep = t.byte();
<a href=#820 id=820 data-nosnippet>820</a> <span class="kw">let </span>class = classes.get(rep);
<a href=#821 id=821 data-nosnippet>821</a> byte += <span class="number">1</span>;
<a href=#822 id=822 data-nosnippet>822</a> <span class="kw">if </span><span class="macro">prev_class !</span>= <span class="prelude-val">Some</span>(class) {
<a href=#823 id=823 data-nosnippet>823</a> f(rep, class, t.next());
<a href=#824 id=824 data-nosnippet>824</a> prev_class = <span class="prelude-val">Some</span>(class);
<a href=#825 id=825 data-nosnippet>825</a> }
<a href=#826 id=826 data-nosnippet>826</a> }
<a href=#827 id=827 data-nosnippet>827</a> <span class="kw">for </span>b <span class="kw">in </span>byte..=<span class="number">255 </span>{
<a href=#828 id=828 data-nosnippet>828</a> <span class="kw">let </span>rep = b.as_u8();
<a href=#829 id=829 data-nosnippet>829</a> <span class="kw">let </span>class = classes.get(rep);
<a href=#830 id=830 data-nosnippet>830</a> <span class="kw">if </span><span class="macro">prev_class !</span>= <span class="prelude-val">Some</span>(class) {
<a href=#831 id=831 data-nosnippet>831</a> f(rep, class, noncontiguous::NFA::FAIL);
<a href=#832 id=832 data-nosnippet>832</a> prev_class = <span class="prelude-val">Some</span>(class);
<a href=#833 id=833 data-nosnippet>833</a> }
<a href=#834 id=834 data-nosnippet>834</a> }
<a href=#835 id=835 data-nosnippet>835</a>}
</code></pre></div></section></main></body></html>

View File

@@ -0,0 +1,327 @@
<!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/lib.rs`."><title>lib.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/</div>lib.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>A library for finding occurrences of many patterns at once. This library
<a href=#3 id=3 data-nosnippet>3</a>provides multiple pattern search principally through an implementation of the
<a href=#4 id=4 data-nosnippet>4</a>[Aho-Corasick algorithm](https://en.wikipedia.org/wiki/Aho%E2%80%93Corasick_algorithm),
<a href=#5 id=5 data-nosnippet>5</a>which builds a fast finite state machine for executing searches in linear time.
<a href=#6 id=6 data-nosnippet>6</a>
<a href=#7 id=7 data-nosnippet>7</a>Additionally, this library provides a number of configuration options for
<a href=#8 id=8 data-nosnippet>8</a>building the automaton that permit controlling the space versus time trade
<a href=#9 id=9 data-nosnippet>9</a>off. Other features include simple ASCII case insensitive matching, finding
<a href=#10 id=10 data-nosnippet>10</a>overlapping matches, replacements, searching streams and even searching and
<a href=#11 id=11 data-nosnippet>11</a>replacing text in streams.
<a href=#12 id=12 data-nosnippet>12</a>
<a href=#13 id=13 data-nosnippet>13</a>Finally, unlike most other Aho-Corasick implementations, this one
<a href=#14 id=14 data-nosnippet>14</a>supports enabling [leftmost-first](MatchKind::LeftmostFirst) or
<a href=#15 id=15 data-nosnippet>15</a>[leftmost-longest](MatchKind::LeftmostLongest) match semantics, using a
<a href=#16 id=16 data-nosnippet>16</a>(seemingly) novel alternative construction algorithm. For more details on what
<a href=#17 id=17 data-nosnippet>17</a>match semantics means, see the [`MatchKind`] type.
<a href=#18 id=18 data-nosnippet>18</a>
<a href=#19 id=19 data-nosnippet>19</a># Overview
<a href=#20 id=20 data-nosnippet>20</a>
<a href=#21 id=21 data-nosnippet>21</a>This section gives a brief overview of the primary types in this crate:
<a href=#22 id=22 data-nosnippet>22</a>
<a href=#23 id=23 data-nosnippet>23</a>* [`AhoCorasick`] is the primary type and represents an Aho-Corasick automaton.
<a href=#24 id=24 data-nosnippet>24</a>This is the type you use to execute searches.
<a href=#25 id=25 data-nosnippet>25</a>* [`AhoCorasickBuilder`] can be used to build an Aho-Corasick automaton, and
<a href=#26 id=26 data-nosnippet>26</a>supports configuring a number of options.
<a href=#27 id=27 data-nosnippet>27</a>* [`Match`] represents a single match reported by an Aho-Corasick automaton.
<a href=#28 id=28 data-nosnippet>28</a>Each match has two pieces of information: the pattern that matched and the
<a href=#29 id=29 data-nosnippet>29</a>start and end byte offsets corresponding to the position in the haystack at
<a href=#30 id=30 data-nosnippet>30</a>which it matched.
<a href=#31 id=31 data-nosnippet>31</a>
<a href=#32 id=32 data-nosnippet>32</a># Example: basic searching
<a href=#33 id=33 data-nosnippet>33</a>
<a href=#34 id=34 data-nosnippet>34</a>This example shows how to search for occurrences of multiple patterns
<a href=#35 id=35 data-nosnippet>35</a>simultaneously. Each match includes the pattern that matched along with the
<a href=#36 id=36 data-nosnippet>36</a>byte offsets of the match.
<a href=#37 id=37 data-nosnippet>37</a>
<a href=#38 id=38 data-nosnippet>38</a>```
<a href=#39 id=39 data-nosnippet>39</a>use aho_corasick::{AhoCorasick, PatternID};
<a href=#40 id=40 data-nosnippet>40</a>
<a href=#41 id=41 data-nosnippet>41</a>let patterns = &amp;["apple", "maple", "Snapple"];
<a href=#42 id=42 data-nosnippet>42</a>let haystack = "Nobody likes maple in their apple flavored Snapple.";
<a href=#43 id=43 data-nosnippet>43</a>
<a href=#44 id=44 data-nosnippet>44</a>let ac = AhoCorasick::new(patterns).unwrap();
<a href=#45 id=45 data-nosnippet>45</a>let mut matches = vec![];
<a href=#46 id=46 data-nosnippet>46</a>for mat in ac.find_iter(haystack) {
<a href=#47 id=47 data-nosnippet>47</a> matches.push((mat.pattern(), mat.start(), mat.end()));
<a href=#48 id=48 data-nosnippet>48</a>}
<a href=#49 id=49 data-nosnippet>49</a>assert_eq!(matches, vec![
<a href=#50 id=50 data-nosnippet>50</a> (PatternID::must(1), 13, 18),
<a href=#51 id=51 data-nosnippet>51</a> (PatternID::must(0), 28, 33),
<a href=#52 id=52 data-nosnippet>52</a> (PatternID::must(2), 43, 50),
<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># Example: case insensitivity
<a href=#57 id=57 data-nosnippet>57</a>
<a href=#58 id=58 data-nosnippet>58</a>This is like the previous example, but matches `Snapple` case insensitively
<a href=#59 id=59 data-nosnippet>59</a>using `AhoCorasickBuilder`:
<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>use aho_corasick::{AhoCorasick, PatternID};
<a href=#63 id=63 data-nosnippet>63</a>
<a href=#64 id=64 data-nosnippet>64</a>let patterns = &amp;["apple", "maple", "snapple"];
<a href=#65 id=65 data-nosnippet>65</a>let haystack = "Nobody likes maple in their apple flavored Snapple.";
<a href=#66 id=66 data-nosnippet>66</a>
<a href=#67 id=67 data-nosnippet>67</a>let ac = AhoCorasick::builder()
<a href=#68 id=68 data-nosnippet>68</a> .ascii_case_insensitive(true)
<a href=#69 id=69 data-nosnippet>69</a> .build(patterns)
<a href=#70 id=70 data-nosnippet>70</a> .unwrap();
<a href=#71 id=71 data-nosnippet>71</a>let mut matches = vec![];
<a href=#72 id=72 data-nosnippet>72</a>for mat in ac.find_iter(haystack) {
<a href=#73 id=73 data-nosnippet>73</a> matches.push((mat.pattern(), mat.start(), mat.end()));
<a href=#74 id=74 data-nosnippet>74</a>}
<a href=#75 id=75 data-nosnippet>75</a>assert_eq!(matches, vec![
<a href=#76 id=76 data-nosnippet>76</a> (PatternID::must(1), 13, 18),
<a href=#77 id=77 data-nosnippet>77</a> (PatternID::must(0), 28, 33),
<a href=#78 id=78 data-nosnippet>78</a> (PatternID::must(2), 43, 50),
<a href=#79 id=79 data-nosnippet>79</a>]);
<a href=#80 id=80 data-nosnippet>80</a>```
<a href=#81 id=81 data-nosnippet>81</a>
<a href=#82 id=82 data-nosnippet>82</a># Example: replacing matches in a stream
<a href=#83 id=83 data-nosnippet>83</a>
<a href=#84 id=84 data-nosnippet>84</a>This example shows how to execute a search and replace on a stream without
<a href=#85 id=85 data-nosnippet>85</a>loading the entire stream into memory first.
<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># #[cfg(feature = "std")] {
<a href=#89 id=89 data-nosnippet>89</a>use aho_corasick::AhoCorasick;
<a href=#90 id=90 data-nosnippet>90</a>
<a href=#91 id=91 data-nosnippet>91</a># fn example() -&gt; Result&lt;(), std::io::Error&gt; {
<a href=#92 id=92 data-nosnippet>92</a>let patterns = &amp;["fox", "brown", "quick"];
<a href=#93 id=93 data-nosnippet>93</a>let replace_with = &amp;["sloth", "grey", "slow"];
<a href=#94 id=94 data-nosnippet>94</a>
<a href=#95 id=95 data-nosnippet>95</a>// In a real example, these might be `std::fs::File`s instead. All you need to
<a href=#96 id=96 data-nosnippet>96</a>// do is supply a pair of `std::io::Read` and `std::io::Write` implementations.
<a href=#97 id=97 data-nosnippet>97</a>let rdr = "The quick brown fox.";
<a href=#98 id=98 data-nosnippet>98</a>let mut wtr = vec![];
<a href=#99 id=99 data-nosnippet>99</a>
<a href=#100 id=100 data-nosnippet>100</a>let ac = AhoCorasick::new(patterns).unwrap();
<a href=#101 id=101 data-nosnippet>101</a>ac.try_stream_replace_all(rdr.as_bytes(), &amp;mut wtr, replace_with)?;
<a href=#102 id=102 data-nosnippet>102</a>assert_eq!(b"The slow grey sloth.".to_vec(), wtr);
<a href=#103 id=103 data-nosnippet>103</a># Ok(()) }; example().unwrap()
<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># Example: finding the leftmost first match
<a href=#108 id=108 data-nosnippet>108</a>
<a href=#109 id=109 data-nosnippet>109</a>In the textbook description of Aho-Corasick, its formulation is typically
<a href=#110 id=110 data-nosnippet>110</a>structured such that it reports all possible matches, even when they overlap
<a href=#111 id=111 data-nosnippet>111</a>with another. In many cases, overlapping matches may not be desired, such as
<a href=#112 id=112 data-nosnippet>112</a>the case of finding all successive non-overlapping matches like you might with
<a href=#113 id=113 data-nosnippet>113</a>a standard regular expression.
<a href=#114 id=114 data-nosnippet>114</a>
<a href=#115 id=115 data-nosnippet>115</a>Unfortunately the "obvious" way to modify the Aho-Corasick algorithm to do
<a href=#116 id=116 data-nosnippet>116</a>this doesn't always work in the expected way, since it will report matches as
<a href=#117 id=117 data-nosnippet>117</a>soon as they are seen. For example, consider matching the regex `Samwise|Sam`
<a href=#118 id=118 data-nosnippet>118</a>against the text `Samwise`. Most regex engines (that are Perl-like, or
<a href=#119 id=119 data-nosnippet>119</a>non-POSIX) will report `Samwise` as a match, but the standard Aho-Corasick
<a href=#120 id=120 data-nosnippet>120</a>algorithm modified for reporting non-overlapping matches will report `Sam`.
<a href=#121 id=121 data-nosnippet>121</a>
<a href=#122 id=122 data-nosnippet>122</a>A novel contribution of this library is the ability to change the match
<a href=#123 id=123 data-nosnippet>123</a>semantics of Aho-Corasick (without additional search time overhead) such that
<a href=#124 id=124 data-nosnippet>124</a>`Samwise` is reported instead. For example, here's the standard approach:
<a href=#125 id=125 data-nosnippet>125</a>
<a href=#126 id=126 data-nosnippet>126</a>```
<a href=#127 id=127 data-nosnippet>127</a>use aho_corasick::AhoCorasick;
<a href=#128 id=128 data-nosnippet>128</a>
<a href=#129 id=129 data-nosnippet>129</a>let patterns = &amp;["Samwise", "Sam"];
<a href=#130 id=130 data-nosnippet>130</a>let haystack = "Samwise";
<a href=#131 id=131 data-nosnippet>131</a>
<a href=#132 id=132 data-nosnippet>132</a>let ac = AhoCorasick::new(patterns).unwrap();
<a href=#133 id=133 data-nosnippet>133</a>let mat = ac.find(haystack).expect("should have a match");
<a href=#134 id=134 data-nosnippet>134</a>assert_eq!("Sam", &amp;haystack[mat.start()..mat.end()]);
<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>And now here's the leftmost-first version, which matches how a Perl-like
<a href=#138 id=138 data-nosnippet>138</a>regex will work:
<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>use aho_corasick::{AhoCorasick, MatchKind};
<a href=#142 id=142 data-nosnippet>142</a>
<a href=#143 id=143 data-nosnippet>143</a>let patterns = &amp;["Samwise", "Sam"];
<a href=#144 id=144 data-nosnippet>144</a>let haystack = "Samwise";
<a href=#145 id=145 data-nosnippet>145</a>
<a href=#146 id=146 data-nosnippet>146</a>let ac = AhoCorasick::builder()
<a href=#147 id=147 data-nosnippet>147</a> .match_kind(MatchKind::LeftmostFirst)
<a href=#148 id=148 data-nosnippet>148</a> .build(patterns)
<a href=#149 id=149 data-nosnippet>149</a> .unwrap();
<a href=#150 id=150 data-nosnippet>150</a>let mat = ac.find(haystack).expect("should have a match");
<a href=#151 id=151 data-nosnippet>151</a>assert_eq!("Samwise", &amp;haystack[mat.start()..mat.end()]);
<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>In addition to leftmost-first semantics, this library also supports
<a href=#155 id=155 data-nosnippet>155</a>leftmost-longest semantics, which match the POSIX behavior of a regular
<a href=#156 id=156 data-nosnippet>156</a>expression alternation. See [`MatchKind`] for more details.
<a href=#157 id=157 data-nosnippet>157</a>
<a href=#158 id=158 data-nosnippet>158</a># Prefilters
<a href=#159 id=159 data-nosnippet>159</a>
<a href=#160 id=160 data-nosnippet>160</a>While an Aho-Corasick automaton can perform admirably when compared to more
<a href=#161 id=161 data-nosnippet>161</a>naive solutions, it is generally slower than more specialized algorithms that
<a href=#162 id=162 data-nosnippet>162</a>are accelerated using vector instructions such as SIMD.
<a href=#163 id=163 data-nosnippet>163</a>
<a href=#164 id=164 data-nosnippet>164</a>For that reason, this library will internally use a "prefilter" to attempt
<a href=#165 id=165 data-nosnippet>165</a>to accelerate searches when possible. Currently, this library has several
<a href=#166 id=166 data-nosnippet>166</a>different algorithms it might use depending on the patterns provided. Once the
<a href=#167 id=167 data-nosnippet>167</a>number of patterns gets too big, prefilters are no longer used.
<a href=#168 id=168 data-nosnippet>168</a>
<a href=#169 id=169 data-nosnippet>169</a>While a prefilter is generally good to have on by default since it works
<a href=#170 id=170 data-nosnippet>170</a>well in the common case, it can lead to less predictable or even sub-optimal
<a href=#171 id=171 data-nosnippet>171</a>performance in some cases. For that reason, prefilters can be explicitly
<a href=#172 id=172 data-nosnippet>172</a>disabled via [`AhoCorasickBuilder::prefilter`].
<a href=#173 id=173 data-nosnippet>173</a>
<a href=#174 id=174 data-nosnippet>174</a># Lower level APIs
<a href=#175 id=175 data-nosnippet>175</a>
<a href=#176 id=176 data-nosnippet>176</a>This crate also provides several sub-modules that collectively expose many of
<a href=#177 id=177 data-nosnippet>177</a>the implementation details of the main [`AhoCorasick`] type. Most users of this
<a href=#178 id=178 data-nosnippet>178</a>library can completely ignore the submodules and their contents, but if you
<a href=#179 id=179 data-nosnippet>179</a>needed finer grained control, some parts of them may be useful to you. Here is
<a href=#180 id=180 data-nosnippet>180</a>a brief overview of each and why you might want to use them:
<a href=#181 id=181 data-nosnippet>181</a>
<a href=#182 id=182 data-nosnippet>182</a>* The [`packed`] sub-module contains a lower level API for using fast
<a href=#183 id=183 data-nosnippet>183</a>vectorized routines for finding a small number of patterns in a haystack.
<a href=#184 id=184 data-nosnippet>184</a>You might want to use this API when you want to completely side-step using
<a href=#185 id=185 data-nosnippet>185</a>Aho-Corasick automata. Otherwise, the fast vectorized routines are used
<a href=#186 id=186 data-nosnippet>186</a>automatically as prefilters for `AhoCorasick` searches whenever possible.
<a href=#187 id=187 data-nosnippet>187</a>* The [`automaton`] sub-module provides a lower level finite state
<a href=#188 id=188 data-nosnippet>188</a>machine interface that the various Aho-Corasick implementations in
<a href=#189 id=189 data-nosnippet>189</a>this crate implement. This sub-module's main contribution is the
<a href=#190 id=190 data-nosnippet>190</a>[`Automaton`](automaton::Automaton) trait, which permits manually walking the
<a href=#191 id=191 data-nosnippet>191</a>state transitions of an Aho-Corasick automaton.
<a href=#192 id=192 data-nosnippet>192</a>* The [`dfa`] and [`nfa`] sub-modules provide DFA and NFA implementations of
<a href=#193 id=193 data-nosnippet>193</a>the aforementioned `Automaton` trait. The main reason one might want to use
<a href=#194 id=194 data-nosnippet>194</a>these sub-modules is to get access to a type that implements the `Automaton`
<a href=#195 id=195 data-nosnippet>195</a>trait. (The top-level `AhoCorasick` type does not implement the `Automaton`
<a href=#196 id=196 data-nosnippet>196</a>trait.)
<a href=#197 id=197 data-nosnippet>197</a>
<a href=#198 id=198 data-nosnippet>198</a>As mentioned above, if you aren't sure whether you need these sub-modules,
<a href=#199 id=199 data-nosnippet>199</a>you should be able to safely ignore them and just focus on the [`AhoCorasick`]
<a href=#200 id=200 data-nosnippet>200</a>type.
<a href=#201 id=201 data-nosnippet>201</a>
<a href=#202 id=202 data-nosnippet>202</a># Crate features
<a href=#203 id=203 data-nosnippet>203</a>
<a href=#204 id=204 data-nosnippet>204</a>This crate exposes a few features for controlling dependency usage and whether
<a href=#205 id=205 data-nosnippet>205</a>this crate can be used without the standard library.
<a href=#206 id=206 data-nosnippet>206</a>
<a href=#207 id=207 data-nosnippet>207</a>* **std** -
<a href=#208 id=208 data-nosnippet>208</a> Enables support for the standard library. This feature is enabled by
<a href=#209 id=209 data-nosnippet>209</a> default. When disabled, only `core` and `alloc` are used. At an API
<a href=#210 id=210 data-nosnippet>210</a> level, enabling `std` enables `std::error::Error` trait impls for the
<a href=#211 id=211 data-nosnippet>211</a> various error types, and higher level stream search routines such as
<a href=#212 id=212 data-nosnippet>212</a> [`AhoCorasick::try_stream_find_iter`]. But the `std` feature is also required
<a href=#213 id=213 data-nosnippet>213</a> to enable vectorized prefilters. Prefilters can greatly accelerate searches,
<a href=#214 id=214 data-nosnippet>214</a> but generally only apply when the number of patterns is small (less than
<a href=#215 id=215 data-nosnippet>215</a> ~100).
<a href=#216 id=216 data-nosnippet>216</a>* **perf-literal** -
<a href=#217 id=217 data-nosnippet>217</a> Enables support for literal prefilters that use vectorized routines from
<a href=#218 id=218 data-nosnippet>218</a> external crates. This feature is enabled by default. If you're only using
<a href=#219 id=219 data-nosnippet>219</a> Aho-Corasick for large numbers of patterns or otherwise can abide lower
<a href=#220 id=220 data-nosnippet>220</a> throughput when searching with a small number of patterns, then it is
<a href=#221 id=221 data-nosnippet>221</a> reasonable to disable this feature.
<a href=#222 id=222 data-nosnippet>222</a>* **logging** -
<a href=#223 id=223 data-nosnippet>223</a> Enables a dependency on the `log` crate and emits messages to aide in
<a href=#224 id=224 data-nosnippet>224</a> diagnostics. This feature is disabled by default.
<a href=#225 id=225 data-nosnippet>225</a>*/
<a href=#226 id=226 data-nosnippet>226</a>
<a href=#227 id=227 data-nosnippet>227</a></span><span class="attr">#![no_std]
<a href=#228 id=228 data-nosnippet>228</a>#![deny(missing_docs)]
<a href=#229 id=229 data-nosnippet>229</a>#![deny(rustdoc::broken_intra_doc_links)]
<a href=#230 id=230 data-nosnippet>230</a>#![cfg_attr(docsrs, feature(doc_cfg))]
<a href=#231 id=231 data-nosnippet>231</a>
<a href=#232 id=232 data-nosnippet>232</a></span><span class="kw">extern crate </span>alloc;
<a href=#233 id=233 data-nosnippet>233</a><span class="attr">#[cfg(any(test, feature = <span class="string">"std"</span>))]
<a href=#234 id=234 data-nosnippet>234</a></span><span class="kw">extern crate </span>std;
<a href=#235 id=235 data-nosnippet>235</a>
<a href=#236 id=236 data-nosnippet>236</a><span class="attr">#[cfg(doctest)]
<a href=#237 id=237 data-nosnippet>237</a></span><span class="macro">doc_comment::doctest!</span>(<span class="string">"../README.md"</span>);
<a href=#238 id=238 data-nosnippet>238</a>
<a href=#239 id=239 data-nosnippet>239</a><span class="attr">#[cfg(feature = <span class="string">"std"</span>)]
<a href=#240 id=240 data-nosnippet>240</a></span><span class="kw">pub use </span><span class="kw">crate</span>::ahocorasick::StreamFindIter;
<a href=#241 id=241 data-nosnippet>241</a><span class="kw">pub use crate</span>::{
<a href=#242 id=242 data-nosnippet>242</a> ahocorasick::{
<a href=#243 id=243 data-nosnippet>243</a> AhoCorasick, AhoCorasickBuilder, AhoCorasickKind, FindIter,
<a href=#244 id=244 data-nosnippet>244</a> FindOverlappingIter,
<a href=#245 id=245 data-nosnippet>245</a> },
<a href=#246 id=246 data-nosnippet>246</a> util::{
<a href=#247 id=247 data-nosnippet>247</a> error::{BuildError, MatchError, MatchErrorKind},
<a href=#248 id=248 data-nosnippet>248</a> primitives::{PatternID, PatternIDError},
<a href=#249 id=249 data-nosnippet>249</a> search::{Anchored, Input, Match, MatchKind, Span, StartKind},
<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="attr">#[macro_use]
<a href=#254 id=254 data-nosnippet>254</a></span><span class="kw">mod </span>macros;
<a href=#255 id=255 data-nosnippet>255</a>
<a href=#256 id=256 data-nosnippet>256</a><span class="kw">mod </span>ahocorasick;
<a href=#257 id=257 data-nosnippet>257</a><span class="kw">pub mod </span>automaton;
<a href=#258 id=258 data-nosnippet>258</a><span class="kw">pub mod </span>dfa;
<a href=#259 id=259 data-nosnippet>259</a><span class="kw">pub mod </span>nfa;
<a href=#260 id=260 data-nosnippet>260</a><span class="kw">pub mod </span>packed;
<a href=#261 id=261 data-nosnippet>261</a><span class="attr">#[cfg(test)]
<a href=#262 id=262 data-nosnippet>262</a></span><span class="kw">mod </span>tests;
<a href=#263 id=263 data-nosnippet>263</a><span class="comment">// I wrote out the module for implementing fst::Automaton only to later realize
<a href=#264 id=264 data-nosnippet>264</a>// that this would make fst a public dependency and fst is not at 1.0 yet. I
<a href=#265 id=265 data-nosnippet>265</a>// decided to just keep the code in tree, but build it only during tests.
<a href=#266 id=266 data-nosnippet>266</a>//
<a href=#267 id=267 data-nosnippet>267</a>// TODO: I think I've changed my mind again. I'm considering pushing it out
<a href=#268 id=268 data-nosnippet>268</a>// into either a separate crate or into 'fst' directly as an optional feature.
<a href=#269 id=269 data-nosnippet>269</a>// #[cfg(test)]
<a href=#270 id=270 data-nosnippet>270</a>// #[allow(dead_code)]
<a href=#271 id=271 data-nosnippet>271</a>// mod transducer;
<a href=#272 id=272 data-nosnippet>272</a></span><span class="kw">pub</span>(<span class="kw">crate</span>) <span class="kw">mod </span>util;
<a href=#273 id=273 data-nosnippet>273</a>
<a href=#274 id=274 data-nosnippet>274</a><span class="attr">#[cfg(test)]
<a href=#275 id=275 data-nosnippet>275</a></span><span class="kw">mod </span>testoibits {
<a href=#276 id=276 data-nosnippet>276</a> <span class="kw">use </span>std::panic::{RefUnwindSafe, UnwindSafe};
<a href=#277 id=277 data-nosnippet>277</a>
<a href=#278 id=278 data-nosnippet>278</a> <span class="kw">use super</span>::<span class="kw-2">*</span>;
<a href=#279 id=279 data-nosnippet>279</a>
<a href=#280 id=280 data-nosnippet>280</a> <span class="kw">fn </span>assert_all&lt;T: Send + Sync + UnwindSafe + RefUnwindSafe&gt;() {}
<a href=#281 id=281 data-nosnippet>281</a>
<a href=#282 id=282 data-nosnippet>282</a> <span class="attr">#[test]
<a href=#283 id=283 data-nosnippet>283</a> </span><span class="kw">fn </span>oibits_main() {
<a href=#284 id=284 data-nosnippet>284</a> assert_all::&lt;AhoCorasick&gt;();
<a href=#285 id=285 data-nosnippet>285</a> assert_all::&lt;AhoCorasickBuilder&gt;();
<a href=#286 id=286 data-nosnippet>286</a> assert_all::&lt;AhoCorasickKind&gt;();
<a href=#287 id=287 data-nosnippet>287</a> assert_all::&lt;FindIter&gt;();
<a href=#288 id=288 data-nosnippet>288</a> assert_all::&lt;FindOverlappingIter&gt;();
<a href=#289 id=289 data-nosnippet>289</a>
<a href=#290 id=290 data-nosnippet>290</a> assert_all::&lt;BuildError&gt;();
<a href=#291 id=291 data-nosnippet>291</a> assert_all::&lt;MatchError&gt;();
<a href=#292 id=292 data-nosnippet>292</a> assert_all::&lt;MatchErrorKind&gt;();
<a href=#293 id=293 data-nosnippet>293</a>
<a href=#294 id=294 data-nosnippet>294</a> assert_all::&lt;Anchored&gt;();
<a href=#295 id=295 data-nosnippet>295</a> assert_all::&lt;Input&gt;();
<a href=#296 id=296 data-nosnippet>296</a> assert_all::&lt;Match&gt;();
<a href=#297 id=297 data-nosnippet>297</a> assert_all::&lt;MatchKind&gt;();
<a href=#298 id=298 data-nosnippet>298</a> assert_all::&lt;Span&gt;();
<a href=#299 id=299 data-nosnippet>299</a> assert_all::&lt;StartKind&gt;();
<a href=#300 id=300 data-nosnippet>300</a> }
<a href=#301 id=301 data-nosnippet>301</a>
<a href=#302 id=302 data-nosnippet>302</a> <span class="attr">#[test]
<a href=#303 id=303 data-nosnippet>303</a> </span><span class="kw">fn </span>oibits_automaton() {
<a href=#304 id=304 data-nosnippet>304</a> <span class="kw">use crate</span>::{automaton, dfa::DFA};
<a href=#305 id=305 data-nosnippet>305</a>
<a href=#306 id=306 data-nosnippet>306</a> assert_all::&lt;automaton::FindIter&lt;DFA&gt;&gt;();
<a href=#307 id=307 data-nosnippet>307</a> assert_all::&lt;automaton::FindOverlappingIter&lt;DFA&gt;&gt;();
<a href=#308 id=308 data-nosnippet>308</a> <span class="attr">#[cfg(feature = <span class="string">"std"</span>)]
<a href=#309 id=309 data-nosnippet>309</a> </span>assert_all::&lt;automaton::StreamFindIter&lt;DFA, std::io::Stdin&gt;&gt;();
<a href=#310 id=310 data-nosnippet>310</a> assert_all::&lt;automaton::OverlappingState&gt;();
<a href=#311 id=311 data-nosnippet>311</a>
<a href=#312 id=312 data-nosnippet>312</a> assert_all::&lt;automaton::Prefilter&gt;();
<a href=#313 id=313 data-nosnippet>313</a> assert_all::&lt;automaton::Candidate&gt;();
<a href=#314 id=314 data-nosnippet>314</a> }
<a href=#315 id=315 data-nosnippet>315</a>
<a href=#316 id=316 data-nosnippet>316</a> <span class="attr">#[test]
<a href=#317 id=317 data-nosnippet>317</a> </span><span class="kw">fn </span>oibits_packed() {
<a href=#318 id=318 data-nosnippet>318</a> <span class="kw">use </span><span class="kw">crate</span>::packed;
<a href=#319 id=319 data-nosnippet>319</a>
<a href=#320 id=320 data-nosnippet>320</a> assert_all::&lt;packed::Config&gt;();
<a href=#321 id=321 data-nosnippet>321</a> assert_all::&lt;packed::Builder&gt;();
<a href=#322 id=322 data-nosnippet>322</a> assert_all::&lt;packed::Searcher&gt;();
<a href=#323 id=323 data-nosnippet>323</a> assert_all::&lt;packed::FindIter&gt;();
<a href=#324 id=324 data-nosnippet>324</a> assert_all::&lt;packed::MatchKind&gt;();
<a href=#325 id=325 data-nosnippet>325</a> }
<a href=#326 id=326 data-nosnippet>326</a>}
</code></pre></div></section></main></body></html>

View File

@@ -0,0 +1,19 @@
<!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/macros.rs`."><title>macros.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/</div>macros.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="attr">#![allow(unused_macros)]
<a href=#2 id=2 data-nosnippet>2</a>
<a href=#3 id=3 data-nosnippet>3</a></span><span class="macro">macro_rules!</span> log {
<a href=#4 id=4 data-nosnippet>4</a> ($(<span class="macro-nonterminal">$tt</span>:tt)<span class="kw-2">*</span>) =&gt; {
<a href=#5 id=5 data-nosnippet>5</a> <span class="attr">#[cfg(feature = <span class="string">"logging"</span>)]
<a href=#6 id=6 data-nosnippet>6</a> </span>{
<a href=#7 id=7 data-nosnippet>7</a> $(<span class="macro-nonterminal">$tt</span>)*
<a href=#8 id=8 data-nosnippet>8</a> }
<a href=#9 id=9 data-nosnippet>9</a> }
<a href=#10 id=10 data-nosnippet>10</a>}
<a href=#11 id=11 data-nosnippet>11</a>
<a href=#12 id=12 data-nosnippet>12</a><span class="macro">macro_rules!</span> debug {
<a href=#13 id=13 data-nosnippet>13</a> ($(<span class="macro-nonterminal">$tt</span>:tt)<span class="kw-2">*</span>) =&gt; { <span class="macro">log!</span>(<span class="macro">log::debug!</span>($(<span class="macro-nonterminal">$tt</span>)<span class="kw-2">*</span>)) }
<a href=#14 id=14 data-nosnippet>14</a>}
<a href=#15 id=15 data-nosnippet>15</a>
<a href=#16 id=16 data-nosnippet>16</a><span class="macro">macro_rules!</span> trace {
<a href=#17 id=17 data-nosnippet>17</a> ($(<span class="macro-nonterminal">$tt</span>:tt)<span class="kw-2">*</span>) =&gt; { <span class="macro">log!</span>(<span class="macro">log::trace!</span>($(<span class="macro-nonterminal">$tt</span>)<span class="kw-2">*</span>)) }
<a href=#18 id=18 data-nosnippet>18</a>}
</code></pre></div></section></main></body></html>

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,41 @@
<!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/nfa/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/nfa/</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="doccomment">/*!
<a href=#2 id=2 data-nosnippet>2</a>Provides direct access to NFA implementations of Aho-Corasick.
<a href=#3 id=3 data-nosnippet>3</a>
<a href=#4 id=4 data-nosnippet>4</a>The principle characteristic of an NFA in this crate is that it may
<a href=#5 id=5 data-nosnippet>5</a>transition through multiple states per byte of haystack. In Aho-Corasick
<a href=#6 id=6 data-nosnippet>6</a>parlance, NFAs follow failure transitions during a search. In contrast,
<a href=#7 id=7 data-nosnippet>7</a>a [`DFA`](crate::dfa::DFA) pre-computes all failure transitions during
<a href=#8 id=8 data-nosnippet>8</a>compilation at the expense of a much bigger memory footprint.
<a href=#9 id=9 data-nosnippet>9</a>
<a href=#10 id=10 data-nosnippet>10</a>Currently, there are two NFA implementations provided: noncontiguous and
<a href=#11 id=11 data-nosnippet>11</a>contiguous. The names reflect their internal representation, and consequently,
<a href=#12 id=12 data-nosnippet>12</a>the trade offs associated with them:
<a href=#13 id=13 data-nosnippet>13</a>
<a href=#14 id=14 data-nosnippet>14</a>* A [`noncontiguous::NFA`] uses a separate allocation for every NFA state to
<a href=#15 id=15 data-nosnippet>15</a>represent its transitions in a sparse format. This is ideal for building an
<a href=#16 id=16 data-nosnippet>16</a>NFA, since it cheaply permits different states to have a different number of
<a href=#17 id=17 data-nosnippet>17</a>transitions. A noncontiguous NFA is where the main Aho-Corasick construction
<a href=#18 id=18 data-nosnippet>18</a>algorithm is implemented. All other Aho-Corasick implementations are built by
<a href=#19 id=19 data-nosnippet>19</a>first constructing a noncontiguous NFA.
<a href=#20 id=20 data-nosnippet>20</a>* A [`contiguous::NFA`] is uses a single allocation to represent all states,
<a href=#21 id=21 data-nosnippet>21</a>while still encoding most states as sparse states but permitting states near
<a href=#22 id=22 data-nosnippet>22</a>the starting state to have a dense representation. The dense representation
<a href=#23 id=23 data-nosnippet>23</a>uses more memory, but permits computing transitions during a search more
<a href=#24 id=24 data-nosnippet>24</a>quickly. By only making the most active states dense (the states near the
<a href=#25 id=25 data-nosnippet>25</a>starting state), a contiguous NFA better balances memory usage with search
<a href=#26 id=26 data-nosnippet>26</a>speed. The single contiguous allocation also uses less overhead per state and
<a href=#27 id=27 data-nosnippet>27</a>enables compression tricks where most states only use 8 bytes of heap memory.
<a href=#28 id=28 data-nosnippet>28</a>
<a href=#29 id=29 data-nosnippet>29</a>When given the choice between these two, you almost always want to pick a
<a href=#30 id=30 data-nosnippet>30</a>contiguous NFA. It takes only a little longer to build, but both its memory
<a href=#31 id=31 data-nosnippet>31</a>usage and search speed are typically much better than a noncontiguous NFA. A
<a href=#32 id=32 data-nosnippet>32</a>noncontiguous NFA is useful when prioritizing build times, or when there are
<a href=#33 id=33 data-nosnippet>33</a>so many patterns that a contiguous NFA could not be built. (Currently, because
<a href=#34 id=34 data-nosnippet>34</a>of both memory and search speed improvements, a contiguous NFA has a smaller
<a href=#35 id=35 data-nosnippet>35</a>internal limit on the total number of NFA states it can represent. But you
<a href=#36 id=36 data-nosnippet>36</a>would likely need to have hundreds of thousands or even millions of patterns
<a href=#37 id=37 data-nosnippet>37</a>before you hit this limit.)
<a href=#38 id=38 data-nosnippet>38</a>*/
<a href=#39 id=39 data-nosnippet>39</a></span><span class="kw">pub mod </span>contiguous;
<a href=#40 id=40 data-nosnippet>40</a><span class="kw">pub mod </span>noncontiguous;
</code></pre></div></section></main></body></html>

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,688 @@
<!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/packed/api.rs`."><title>api.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/packed/</div>api.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::sync::Arc;
<a href=#2 id=2 data-nosnippet>2</a>
<a href=#3 id=3 data-nosnippet>3</a><span class="kw">use crate</span>::{
<a href=#4 id=4 data-nosnippet>4</a> packed::{pattern::Patterns, rabinkarp::RabinKarp, teddy},
<a href=#5 id=5 data-nosnippet>5</a> util::search::{Match, Span},
<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="doccomment">/// This is a limit placed on the total number of patterns we're willing to try
<a href=#9 id=9 data-nosnippet>9</a>/// and match at once. As more sophisticated algorithms are added, this number
<a href=#10 id=10 data-nosnippet>10</a>/// may be increased.
<a href=#11 id=11 data-nosnippet>11</a></span><span class="kw">const </span>PATTERN_LIMIT: usize = <span class="number">128</span>;
<a href=#12 id=12 data-nosnippet>12</a>
<a href=#13 id=13 data-nosnippet>13</a><span class="doccomment">/// A knob for controlling the match semantics of a packed multiple string
<a href=#14 id=14 data-nosnippet>14</a>/// searcher.
<a href=#15 id=15 data-nosnippet>15</a>///
<a href=#16 id=16 data-nosnippet>16</a>/// This differs from the [`MatchKind`](crate::MatchKind) type in the top-level
<a href=#17 id=17 data-nosnippet>17</a>/// crate module in that it doesn't support "standard" match semantics,
<a href=#18 id=18 data-nosnippet>18</a>/// and instead only supports leftmost-first or leftmost-longest. Namely,
<a href=#19 id=19 data-nosnippet>19</a>/// "standard" semantics cannot be easily supported by packed searchers.
<a href=#20 id=20 data-nosnippet>20</a>///
<a href=#21 id=21 data-nosnippet>21</a>/// For more information on the distinction between leftmost-first and
<a href=#22 id=22 data-nosnippet>22</a>/// leftmost-longest, see the docs on the top-level `MatchKind` type.
<a href=#23 id=23 data-nosnippet>23</a>///
<a href=#24 id=24 data-nosnippet>24</a>/// Unlike the top-level `MatchKind` type, the default match semantics for this
<a href=#25 id=25 data-nosnippet>25</a>/// type are leftmost-first.
<a href=#26 id=26 data-nosnippet>26</a></span><span class="attr">#[derive(Clone, Copy, Debug, Eq, PartialEq)]
<a href=#27 id=27 data-nosnippet>27</a>#[non_exhaustive]
<a href=#28 id=28 data-nosnippet>28</a></span><span class="kw">pub enum </span>MatchKind {
<a href=#29 id=29 data-nosnippet>29</a> <span class="doccomment">/// Use leftmost-first match semantics, which reports leftmost matches.
<a href=#30 id=30 data-nosnippet>30</a> /// When there are multiple possible leftmost matches, the match
<a href=#31 id=31 data-nosnippet>31</a> /// corresponding to the pattern that appeared earlier when constructing
<a href=#32 id=32 data-nosnippet>32</a> /// the automaton is reported.
<a href=#33 id=33 data-nosnippet>33</a> ///
<a href=#34 id=34 data-nosnippet>34</a> /// This is the default.
<a href=#35 id=35 data-nosnippet>35</a> </span>LeftmostFirst,
<a href=#36 id=36 data-nosnippet>36</a> <span class="doccomment">/// Use leftmost-longest match semantics, which reports leftmost matches.
<a href=#37 id=37 data-nosnippet>37</a> /// When there are multiple possible leftmost matches, the longest match
<a href=#38 id=38 data-nosnippet>38</a> /// is chosen.
<a href=#39 id=39 data-nosnippet>39</a> </span>LeftmostLongest,
<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><span class="kw">impl </span>Default <span class="kw">for </span>MatchKind {
<a href=#43 id=43 data-nosnippet>43</a> <span class="kw">fn </span>default() -&gt; MatchKind {
<a href=#44 id=44 data-nosnippet>44</a> MatchKind::LeftmostFirst
<a href=#45 id=45 data-nosnippet>45</a> }
<a href=#46 id=46 data-nosnippet>46</a>}
<a href=#47 id=47 data-nosnippet>47</a>
<a href=#48 id=48 data-nosnippet>48</a><span class="doccomment">/// The configuration for a packed multiple pattern searcher.
<a href=#49 id=49 data-nosnippet>49</a>///
<a href=#50 id=50 data-nosnippet>50</a>/// The configuration is currently limited only to being able to select the
<a href=#51 id=51 data-nosnippet>51</a>/// match semantics (leftmost-first or leftmost-longest) of a searcher. In the
<a href=#52 id=52 data-nosnippet>52</a>/// future, more knobs may be made available.
<a href=#53 id=53 data-nosnippet>53</a>///
<a href=#54 id=54 data-nosnippet>54</a>/// A configuration produces a [`packed::Builder`](Builder), which in turn can
<a href=#55 id=55 data-nosnippet>55</a>/// be used to construct a [`packed::Searcher`](Searcher) for searching.
<a href=#56 id=56 data-nosnippet>56</a>///
<a href=#57 id=57 data-nosnippet>57</a>/// # Example
<a href=#58 id=58 data-nosnippet>58</a>///
<a href=#59 id=59 data-nosnippet>59</a>/// This example shows how to use leftmost-longest semantics instead of the
<a href=#60 id=60 data-nosnippet>60</a>/// default (leftmost-first).
<a href=#61 id=61 data-nosnippet>61</a>///
<a href=#62 id=62 data-nosnippet>62</a>/// ```
<a href=#63 id=63 data-nosnippet>63</a>/// use aho_corasick::{packed::{Config, MatchKind}, PatternID};
<a href=#64 id=64 data-nosnippet>64</a>///
<a href=#65 id=65 data-nosnippet>65</a>/// # fn example() -&gt; Option&lt;()&gt; {
<a href=#66 id=66 data-nosnippet>66</a>/// let searcher = Config::new()
<a href=#67 id=67 data-nosnippet>67</a>/// .match_kind(MatchKind::LeftmostLongest)
<a href=#68 id=68 data-nosnippet>68</a>/// .builder()
<a href=#69 id=69 data-nosnippet>69</a>/// .add("foo")
<a href=#70 id=70 data-nosnippet>70</a>/// .add("foobar")
<a href=#71 id=71 data-nosnippet>71</a>/// .build()?;
<a href=#72 id=72 data-nosnippet>72</a>/// let matches: Vec&lt;PatternID&gt; = searcher
<a href=#73 id=73 data-nosnippet>73</a>/// .find_iter("foobar")
<a href=#74 id=74 data-nosnippet>74</a>/// .map(|mat| mat.pattern())
<a href=#75 id=75 data-nosnippet>75</a>/// .collect();
<a href=#76 id=76 data-nosnippet>76</a>/// assert_eq!(vec![PatternID::must(1)], matches);
<a href=#77 id=77 data-nosnippet>77</a>/// # Some(()) }
<a href=#78 id=78 data-nosnippet>78</a>/// # if cfg!(all(feature = "std", any(
<a href=#79 id=79 data-nosnippet>79</a>/// # target_arch = "x86_64", target_arch = "aarch64",
<a href=#80 id=80 data-nosnippet>80</a>/// # ))) {
<a href=#81 id=81 data-nosnippet>81</a>/// # example().unwrap()
<a href=#82 id=82 data-nosnippet>82</a>/// # } else {
<a href=#83 id=83 data-nosnippet>83</a>/// # assert!(example().is_none());
<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><span class="attr">#[derive(Clone, Debug)]
<a href=#87 id=87 data-nosnippet>87</a></span><span class="kw">pub struct </span>Config {
<a href=#88 id=88 data-nosnippet>88</a> kind: MatchKind,
<a href=#89 id=89 data-nosnippet>89</a> force: <span class="prelude-ty">Option</span>&lt;ForceAlgorithm&gt;,
<a href=#90 id=90 data-nosnippet>90</a> only_teddy_fat: <span class="prelude-ty">Option</span>&lt;bool&gt;,
<a href=#91 id=91 data-nosnippet>91</a> only_teddy_256bit: <span class="prelude-ty">Option</span>&lt;bool&gt;,
<a href=#92 id=92 data-nosnippet>92</a> heuristic_pattern_limits: bool,
<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><span class="doccomment">/// An internal option for forcing the use of a particular packed algorithm.
<a href=#96 id=96 data-nosnippet>96</a>///
<a href=#97 id=97 data-nosnippet>97</a>/// When an algorithm is forced, if a searcher could not be constructed for it,
<a href=#98 id=98 data-nosnippet>98</a>/// then no searcher will be returned even if an alternative algorithm would
<a href=#99 id=99 data-nosnippet>99</a>/// work.
<a href=#100 id=100 data-nosnippet>100</a></span><span class="attr">#[derive(Clone, Debug)]
<a href=#101 id=101 data-nosnippet>101</a></span><span class="kw">enum </span>ForceAlgorithm {
<a href=#102 id=102 data-nosnippet>102</a> Teddy,
<a href=#103 id=103 data-nosnippet>103</a> RabinKarp,
<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><span class="kw">impl </span>Default <span class="kw">for </span>Config {
<a href=#107 id=107 data-nosnippet>107</a> <span class="kw">fn </span>default() -&gt; Config {
<a href=#108 id=108 data-nosnippet>108</a> Config::new()
<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="kw">impl </span>Config {
<a href=#113 id=113 data-nosnippet>113</a> <span class="doccomment">/// Create a new default configuration. A default configuration uses
<a href=#114 id=114 data-nosnippet>114</a> /// leftmost-first match semantics.
<a href=#115 id=115 data-nosnippet>115</a> </span><span class="kw">pub fn </span>new() -&gt; Config {
<a href=#116 id=116 data-nosnippet>116</a> Config {
<a href=#117 id=117 data-nosnippet>117</a> kind: MatchKind::LeftmostFirst,
<a href=#118 id=118 data-nosnippet>118</a> force: <span class="prelude-val">None</span>,
<a href=#119 id=119 data-nosnippet>119</a> only_teddy_fat: <span class="prelude-val">None</span>,
<a href=#120 id=120 data-nosnippet>120</a> only_teddy_256bit: <span class="prelude-val">None</span>,
<a href=#121 id=121 data-nosnippet>121</a> heuristic_pattern_limits: <span class="bool-val">true</span>,
<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="doccomment">/// Create a packed builder from this configuration. The builder can be
<a href=#126 id=126 data-nosnippet>126</a> /// used to accumulate patterns and create a [`Searcher`] from them.
<a href=#127 id=127 data-nosnippet>127</a> </span><span class="kw">pub fn </span>builder(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; Builder {
<a href=#128 id=128 data-nosnippet>128</a> Builder::from_config(<span class="self">self</span>.clone())
<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="doccomment">/// Set the match semantics for this configuration.
<a href=#132 id=132 data-nosnippet>132</a> </span><span class="kw">pub fn </span>match_kind(<span class="kw-2">&amp;mut </span><span class="self">self</span>, kind: MatchKind) -&gt; <span class="kw-2">&amp;mut </span>Config {
<a href=#133 id=133 data-nosnippet>133</a> <span class="self">self</span>.kind = kind;
<a href=#134 id=134 data-nosnippet>134</a> <span class="self">self
<a href=#135 id=135 data-nosnippet>135</a> </span>}
<a href=#136 id=136 data-nosnippet>136</a>
<a href=#137 id=137 data-nosnippet>137</a> <span class="doccomment">/// An undocumented method for forcing the use of the Teddy algorithm.
<a href=#138 id=138 data-nosnippet>138</a> ///
<a href=#139 id=139 data-nosnippet>139</a> /// This is only exposed for more precise testing and benchmarks. Callers
<a href=#140 id=140 data-nosnippet>140</a> /// should not use it as it is not part of the API stability guarantees of
<a href=#141 id=141 data-nosnippet>141</a> /// this crate.
<a href=#142 id=142 data-nosnippet>142</a> </span><span class="attr">#[doc(hidden)]
<a href=#143 id=143 data-nosnippet>143</a> </span><span class="kw">pub fn </span>only_teddy(<span class="kw-2">&amp;mut </span><span class="self">self</span>, yes: bool) -&gt; <span class="kw-2">&amp;mut </span>Config {
<a href=#144 id=144 data-nosnippet>144</a> <span class="kw">if </span>yes {
<a href=#145 id=145 data-nosnippet>145</a> <span class="self">self</span>.force = <span class="prelude-val">Some</span>(ForceAlgorithm::Teddy);
<a href=#146 id=146 data-nosnippet>146</a> } <span class="kw">else </span>{
<a href=#147 id=147 data-nosnippet>147</a> <span class="self">self</span>.force = <span class="prelude-val">None</span>;
<a href=#148 id=148 data-nosnippet>148</a> }
<a href=#149 id=149 data-nosnippet>149</a> <span class="self">self
<a href=#150 id=150 data-nosnippet>150</a> </span>}
<a href=#151 id=151 data-nosnippet>151</a>
<a href=#152 id=152 data-nosnippet>152</a> <span class="doccomment">/// An undocumented method for forcing the use of the Fat Teddy algorithm.
<a href=#153 id=153 data-nosnippet>153</a> ///
<a href=#154 id=154 data-nosnippet>154</a> /// This is only exposed for more precise testing and benchmarks. Callers
<a href=#155 id=155 data-nosnippet>155</a> /// should not use it as it is not part of the API stability guarantees of
<a href=#156 id=156 data-nosnippet>156</a> /// this crate.
<a href=#157 id=157 data-nosnippet>157</a> </span><span class="attr">#[doc(hidden)]
<a href=#158 id=158 data-nosnippet>158</a> </span><span class="kw">pub fn </span>only_teddy_fat(<span class="kw-2">&amp;mut </span><span class="self">self</span>, yes: <span class="prelude-ty">Option</span>&lt;bool&gt;) -&gt; <span class="kw-2">&amp;mut </span>Config {
<a href=#159 id=159 data-nosnippet>159</a> <span class="self">self</span>.only_teddy_fat = yes;
<a href=#160 id=160 data-nosnippet>160</a> <span class="self">self
<a href=#161 id=161 data-nosnippet>161</a> </span>}
<a href=#162 id=162 data-nosnippet>162</a>
<a href=#163 id=163 data-nosnippet>163</a> <span class="doccomment">/// An undocumented method for forcing the use of SSE (`Some(false)`) or
<a href=#164 id=164 data-nosnippet>164</a> /// AVX (`Some(true)`) algorithms.
<a href=#165 id=165 data-nosnippet>165</a> ///
<a href=#166 id=166 data-nosnippet>166</a> /// This is only exposed for more precise testing and benchmarks. Callers
<a href=#167 id=167 data-nosnippet>167</a> /// should not use it as it is not part of the API stability guarantees of
<a href=#168 id=168 data-nosnippet>168</a> /// this crate.
<a href=#169 id=169 data-nosnippet>169</a> </span><span class="attr">#[doc(hidden)]
<a href=#170 id=170 data-nosnippet>170</a> </span><span class="kw">pub fn </span>only_teddy_256bit(<span class="kw-2">&amp;mut </span><span class="self">self</span>, yes: <span class="prelude-ty">Option</span>&lt;bool&gt;) -&gt; <span class="kw-2">&amp;mut </span>Config {
<a href=#171 id=171 data-nosnippet>171</a> <span class="self">self</span>.only_teddy_256bit = yes;
<a href=#172 id=172 data-nosnippet>172</a> <span class="self">self
<a href=#173 id=173 data-nosnippet>173</a> </span>}
<a href=#174 id=174 data-nosnippet>174</a>
<a href=#175 id=175 data-nosnippet>175</a> <span class="doccomment">/// An undocumented method for forcing the use of the Rabin-Karp algorithm.
<a href=#176 id=176 data-nosnippet>176</a> ///
<a href=#177 id=177 data-nosnippet>177</a> /// This is only exposed for more precise testing and benchmarks. Callers
<a href=#178 id=178 data-nosnippet>178</a> /// should not use it as it is not part of the API stability guarantees of
<a href=#179 id=179 data-nosnippet>179</a> /// this crate.
<a href=#180 id=180 data-nosnippet>180</a> </span><span class="attr">#[doc(hidden)]
<a href=#181 id=181 data-nosnippet>181</a> </span><span class="kw">pub fn </span>only_rabin_karp(<span class="kw-2">&amp;mut </span><span class="self">self</span>, yes: bool) -&gt; <span class="kw-2">&amp;mut </span>Config {
<a href=#182 id=182 data-nosnippet>182</a> <span class="kw">if </span>yes {
<a href=#183 id=183 data-nosnippet>183</a> <span class="self">self</span>.force = <span class="prelude-val">Some</span>(ForceAlgorithm::RabinKarp);
<a href=#184 id=184 data-nosnippet>184</a> } <span class="kw">else </span>{
<a href=#185 id=185 data-nosnippet>185</a> <span class="self">self</span>.force = <span class="prelude-val">None</span>;
<a href=#186 id=186 data-nosnippet>186</a> }
<a href=#187 id=187 data-nosnippet>187</a> <span class="self">self
<a href=#188 id=188 data-nosnippet>188</a> </span>}
<a href=#189 id=189 data-nosnippet>189</a>
<a href=#190 id=190 data-nosnippet>190</a> <span class="doccomment">/// Request that heuristic limitations on the number of patterns be
<a href=#191 id=191 data-nosnippet>191</a> /// employed. This useful to disable for benchmarking where one wants to
<a href=#192 id=192 data-nosnippet>192</a> /// explore how Teddy performs on large number of patterns even if the
<a href=#193 id=193 data-nosnippet>193</a> /// heuristics would otherwise refuse construction.
<a href=#194 id=194 data-nosnippet>194</a> ///
<a href=#195 id=195 data-nosnippet>195</a> /// This is enabled by default.
<a href=#196 id=196 data-nosnippet>196</a> </span><span class="kw">pub fn </span>heuristic_pattern_limits(<span class="kw-2">&amp;mut </span><span class="self">self</span>, yes: bool) -&gt; <span class="kw-2">&amp;mut </span>Config {
<a href=#197 id=197 data-nosnippet>197</a> <span class="self">self</span>.heuristic_pattern_limits = yes;
<a href=#198 id=198 data-nosnippet>198</a> <span class="self">self
<a href=#199 id=199 data-nosnippet>199</a> </span>}
<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="doccomment">/// A builder for constructing a packed searcher from a collection of patterns.
<a href=#203 id=203 data-nosnippet>203</a>///
<a href=#204 id=204 data-nosnippet>204</a>/// # Example
<a href=#205 id=205 data-nosnippet>205</a>///
<a href=#206 id=206 data-nosnippet>206</a>/// This example shows how to use a builder to construct a searcher. By
<a href=#207 id=207 data-nosnippet>207</a>/// default, leftmost-first match semantics are used.
<a href=#208 id=208 data-nosnippet>208</a>///
<a href=#209 id=209 data-nosnippet>209</a>/// ```
<a href=#210 id=210 data-nosnippet>210</a>/// use aho_corasick::{packed::{Builder, MatchKind}, PatternID};
<a href=#211 id=211 data-nosnippet>211</a>///
<a href=#212 id=212 data-nosnippet>212</a>/// # fn example() -&gt; Option&lt;()&gt; {
<a href=#213 id=213 data-nosnippet>213</a>/// let searcher = Builder::new()
<a href=#214 id=214 data-nosnippet>214</a>/// .add("foobar")
<a href=#215 id=215 data-nosnippet>215</a>/// .add("foo")
<a href=#216 id=216 data-nosnippet>216</a>/// .build()?;
<a href=#217 id=217 data-nosnippet>217</a>/// let matches: Vec&lt;PatternID&gt; = searcher
<a href=#218 id=218 data-nosnippet>218</a>/// .find_iter("foobar")
<a href=#219 id=219 data-nosnippet>219</a>/// .map(|mat| mat.pattern())
<a href=#220 id=220 data-nosnippet>220</a>/// .collect();
<a href=#221 id=221 data-nosnippet>221</a>/// assert_eq!(vec![PatternID::ZERO], matches);
<a href=#222 id=222 data-nosnippet>222</a>/// # Some(()) }
<a href=#223 id=223 data-nosnippet>223</a>/// # if cfg!(all(feature = "std", any(
<a href=#224 id=224 data-nosnippet>224</a>/// # target_arch = "x86_64", target_arch = "aarch64",
<a href=#225 id=225 data-nosnippet>225</a>/// # ))) {
<a href=#226 id=226 data-nosnippet>226</a>/// # example().unwrap()
<a href=#227 id=227 data-nosnippet>227</a>/// # } else {
<a href=#228 id=228 data-nosnippet>228</a>/// # assert!(example().is_none());
<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><span class="attr">#[derive(Clone, Debug)]
<a href=#232 id=232 data-nosnippet>232</a></span><span class="kw">pub struct </span>Builder {
<a href=#233 id=233 data-nosnippet>233</a> <span class="doccomment">/// The configuration of this builder and subsequent matcher.
<a href=#234 id=234 data-nosnippet>234</a> </span>config: Config,
<a href=#235 id=235 data-nosnippet>235</a> <span class="doccomment">/// Set to true if the builder detects that a matcher cannot be built.
<a href=#236 id=236 data-nosnippet>236</a> </span>inert: bool,
<a href=#237 id=237 data-nosnippet>237</a> <span class="doccomment">/// The patterns provided by the caller.
<a href=#238 id=238 data-nosnippet>238</a> </span>patterns: Patterns,
<a href=#239 id=239 data-nosnippet>239</a>}
<a href=#240 id=240 data-nosnippet>240</a>
<a href=#241 id=241 data-nosnippet>241</a><span class="kw">impl </span>Builder {
<a href=#242 id=242 data-nosnippet>242</a> <span class="doccomment">/// Create a new builder for constructing a multi-pattern searcher. This
<a href=#243 id=243 data-nosnippet>243</a> /// constructor uses the default configuration.
<a href=#244 id=244 data-nosnippet>244</a> </span><span class="kw">pub fn </span>new() -&gt; Builder {
<a href=#245 id=245 data-nosnippet>245</a> Builder::from_config(Config::new())
<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">fn </span>from_config(config: Config) -&gt; Builder {
<a href=#249 id=249 data-nosnippet>249</a> Builder { config, inert: <span class="bool-val">false</span>, patterns: Patterns::new() }
<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> <span class="doccomment">/// Build a searcher from the patterns added to this builder so far.
<a href=#253 id=253 data-nosnippet>253</a> </span><span class="kw">pub fn </span>build(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; <span class="prelude-ty">Option</span>&lt;Searcher&gt; {
<a href=#254 id=254 data-nosnippet>254</a> <span class="kw">if </span><span class="self">self</span>.inert || <span class="self">self</span>.patterns.is_empty() {
<a href=#255 id=255 data-nosnippet>255</a> <span class="kw">return </span><span class="prelude-val">None</span>;
<a href=#256 id=256 data-nosnippet>256</a> }
<a href=#257 id=257 data-nosnippet>257</a> <span class="kw">let </span><span class="kw-2">mut </span>patterns = <span class="self">self</span>.patterns.clone();
<a href=#258 id=258 data-nosnippet>258</a> patterns.set_match_kind(<span class="self">self</span>.config.kind);
<a href=#259 id=259 data-nosnippet>259</a> <span class="kw">let </span>patterns = Arc::new(patterns);
<a href=#260 id=260 data-nosnippet>260</a> <span class="kw">let </span>rabinkarp = RabinKarp::new(<span class="kw-2">&amp;</span>patterns);
<a href=#261 id=261 data-nosnippet>261</a> <span class="comment">// Effectively, we only want to return a searcher if we can use Teddy,
<a href=#262 id=262 data-nosnippet>262</a> // since Teddy is our only fast packed searcher at the moment.
<a href=#263 id=263 data-nosnippet>263</a> // Rabin-Karp is only used when searching haystacks smaller than what
<a href=#264 id=264 data-nosnippet>264</a> // Teddy can support. Thus, the only way to get a Rabin-Karp searcher
<a href=#265 id=265 data-nosnippet>265</a> // is to force it using undocumented APIs (for tests/benchmarks).
<a href=#266 id=266 data-nosnippet>266</a> </span><span class="kw">let </span>(search_kind, minimum_len) = <span class="kw">match </span><span class="self">self</span>.config.force {
<a href=#267 id=267 data-nosnippet>267</a> <span class="prelude-val">None </span>| <span class="prelude-val">Some</span>(ForceAlgorithm::Teddy) =&gt; {
<a href=#268 id=268 data-nosnippet>268</a> <span class="macro">debug!</span>(<span class="string">"trying to build Teddy packed matcher"</span>);
<a href=#269 id=269 data-nosnippet>269</a> <span class="kw">let </span>teddy = <span class="kw">match </span><span class="self">self</span>.build_teddy(Arc::clone(<span class="kw-2">&amp;</span>patterns)) {
<a href=#270 id=270 data-nosnippet>270</a> <span class="prelude-val">None </span>=&gt; <span class="kw">return </span><span class="prelude-val">None</span>,
<a href=#271 id=271 data-nosnippet>271</a> <span class="prelude-val">Some</span>(teddy) =&gt; teddy,
<a href=#272 id=272 data-nosnippet>272</a> };
<a href=#273 id=273 data-nosnippet>273</a> <span class="kw">let </span>minimum_len = teddy.minimum_len();
<a href=#274 id=274 data-nosnippet>274</a> (SearchKind::Teddy(teddy), minimum_len)
<a href=#275 id=275 data-nosnippet>275</a> }
<a href=#276 id=276 data-nosnippet>276</a> <span class="prelude-val">Some</span>(ForceAlgorithm::RabinKarp) =&gt; {
<a href=#277 id=277 data-nosnippet>277</a> <span class="macro">debug!</span>(<span class="string">"using Rabin-Karp packed matcher"</span>);
<a href=#278 id=278 data-nosnippet>278</a> (SearchKind::RabinKarp, <span class="number">0</span>)
<a href=#279 id=279 data-nosnippet>279</a> }
<a href=#280 id=280 data-nosnippet>280</a> };
<a href=#281 id=281 data-nosnippet>281</a> <span class="prelude-val">Some</span>(Searcher { patterns, rabinkarp, search_kind, minimum_len })
<a href=#282 id=282 data-nosnippet>282</a> }
<a href=#283 id=283 data-nosnippet>283</a>
<a href=#284 id=284 data-nosnippet>284</a> <span class="kw">fn </span>build_teddy(<span class="kw-2">&amp;</span><span class="self">self</span>, patterns: Arc&lt;Patterns&gt;) -&gt; <span class="prelude-ty">Option</span>&lt;teddy::Searcher&gt; {
<a href=#285 id=285 data-nosnippet>285</a> teddy::Builder::new()
<a href=#286 id=286 data-nosnippet>286</a> .only_256bit(<span class="self">self</span>.config.only_teddy_256bit)
<a href=#287 id=287 data-nosnippet>287</a> .only_fat(<span class="self">self</span>.config.only_teddy_fat)
<a href=#288 id=288 data-nosnippet>288</a> .heuristic_pattern_limits(<span class="self">self</span>.config.heuristic_pattern_limits)
<a href=#289 id=289 data-nosnippet>289</a> .build(patterns)
<a href=#290 id=290 data-nosnippet>290</a> }
<a href=#291 id=291 data-nosnippet>291</a>
<a href=#292 id=292 data-nosnippet>292</a> <span class="doccomment">/// Add the given pattern to this set to match.
<a href=#293 id=293 data-nosnippet>293</a> ///
<a href=#294 id=294 data-nosnippet>294</a> /// The order in which patterns are added is significant. Namely, when
<a href=#295 id=295 data-nosnippet>295</a> /// using leftmost-first match semantics, then when multiple patterns can
<a href=#296 id=296 data-nosnippet>296</a> /// match at a particular location, the pattern that was added first is
<a href=#297 id=297 data-nosnippet>297</a> /// used as the match.
<a href=#298 id=298 data-nosnippet>298</a> ///
<a href=#299 id=299 data-nosnippet>299</a> /// If the number of patterns added exceeds the amount supported by packed
<a href=#300 id=300 data-nosnippet>300</a> /// searchers, then the builder will stop accumulating patterns and render
<a href=#301 id=301 data-nosnippet>301</a> /// itself inert. At this point, constructing a searcher will always return
<a href=#302 id=302 data-nosnippet>302</a> /// `None`.
<a href=#303 id=303 data-nosnippet>303</a> </span><span class="kw">pub fn </span>add&lt;P: AsRef&lt;[u8]&gt;&gt;(<span class="kw-2">&amp;mut </span><span class="self">self</span>, pattern: P) -&gt; <span class="kw-2">&amp;mut </span>Builder {
<a href=#304 id=304 data-nosnippet>304</a> <span class="kw">if </span><span class="self">self</span>.inert {
<a href=#305 id=305 data-nosnippet>305</a> <span class="kw">return </span><span class="self">self</span>;
<a href=#306 id=306 data-nosnippet>306</a> } <span class="kw">else if </span><span class="self">self</span>.patterns.len() &gt;= PATTERN_LIMIT {
<a href=#307 id=307 data-nosnippet>307</a> <span class="self">self</span>.inert = <span class="bool-val">true</span>;
<a href=#308 id=308 data-nosnippet>308</a> <span class="self">self</span>.patterns.reset();
<a href=#309 id=309 data-nosnippet>309</a> <span class="kw">return </span><span class="self">self</span>;
<a href=#310 id=310 data-nosnippet>310</a> }
<a href=#311 id=311 data-nosnippet>311</a> <span class="comment">// Just in case PATTERN_LIMIT increases beyond u16::MAX.
<a href=#312 id=312 data-nosnippet>312</a> </span><span class="macro">assert!</span>(<span class="self">self</span>.patterns.len() &lt;= core::u16::MAX <span class="kw">as </span>usize);
<a href=#313 id=313 data-nosnippet>313</a>
<a href=#314 id=314 data-nosnippet>314</a> <span class="kw">let </span>pattern = pattern.as_ref();
<a href=#315 id=315 data-nosnippet>315</a> <span class="kw">if </span>pattern.is_empty() {
<a href=#316 id=316 data-nosnippet>316</a> <span class="self">self</span>.inert = <span class="bool-val">true</span>;
<a href=#317 id=317 data-nosnippet>317</a> <span class="self">self</span>.patterns.reset();
<a href=#318 id=318 data-nosnippet>318</a> <span class="kw">return </span><span class="self">self</span>;
<a href=#319 id=319 data-nosnippet>319</a> }
<a href=#320 id=320 data-nosnippet>320</a> <span class="self">self</span>.patterns.add(pattern);
<a href=#321 id=321 data-nosnippet>321</a> <span class="self">self
<a href=#322 id=322 data-nosnippet>322</a> </span>}
<a href=#323 id=323 data-nosnippet>323</a>
<a href=#324 id=324 data-nosnippet>324</a> <span class="doccomment">/// Add the given iterator of patterns to this set to match.
<a href=#325 id=325 data-nosnippet>325</a> ///
<a href=#326 id=326 data-nosnippet>326</a> /// The iterator must yield elements that can be converted into a `&amp;[u8]`.
<a href=#327 id=327 data-nosnippet>327</a> ///
<a href=#328 id=328 data-nosnippet>328</a> /// The order in which patterns are added is significant. Namely, when
<a href=#329 id=329 data-nosnippet>329</a> /// using leftmost-first match semantics, then when multiple patterns can
<a href=#330 id=330 data-nosnippet>330</a> /// match at a particular location, the pattern that was added first is
<a href=#331 id=331 data-nosnippet>331</a> /// used as the match.
<a href=#332 id=332 data-nosnippet>332</a> ///
<a href=#333 id=333 data-nosnippet>333</a> /// If the number of patterns added exceeds the amount supported by packed
<a href=#334 id=334 data-nosnippet>334</a> /// searchers, then the builder will stop accumulating patterns and render
<a href=#335 id=335 data-nosnippet>335</a> /// itself inert. At this point, constructing a searcher will always return
<a href=#336 id=336 data-nosnippet>336</a> /// `None`.
<a href=#337 id=337 data-nosnippet>337</a> </span><span class="kw">pub fn </span>extend&lt;I, P&gt;(<span class="kw-2">&amp;mut </span><span class="self">self</span>, patterns: I) -&gt; <span class="kw-2">&amp;mut </span>Builder
<a href=#338 id=338 data-nosnippet>338</a> <span class="kw">where
<a href=#339 id=339 data-nosnippet>339</a> </span>I: IntoIterator&lt;Item = P&gt;,
<a href=#340 id=340 data-nosnippet>340</a> P: AsRef&lt;[u8]&gt;,
<a href=#341 id=341 data-nosnippet>341</a> {
<a href=#342 id=342 data-nosnippet>342</a> <span class="kw">for </span>p <span class="kw">in </span>patterns {
<a href=#343 id=343 data-nosnippet>343</a> <span class="self">self</span>.add(p);
<a href=#344 id=344 data-nosnippet>344</a> }
<a href=#345 id=345 data-nosnippet>345</a> <span class="self">self
<a href=#346 id=346 data-nosnippet>346</a> </span>}
<a href=#347 id=347 data-nosnippet>347</a>
<a href=#348 id=348 data-nosnippet>348</a> <span class="doccomment">/// Returns the number of patterns added to this builder.
<a href=#349 id=349 data-nosnippet>349</a> </span><span class="kw">pub fn </span>len(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; usize {
<a href=#350 id=350 data-nosnippet>350</a> <span class="self">self</span>.patterns.len()
<a href=#351 id=351 data-nosnippet>351</a> }
<a href=#352 id=352 data-nosnippet>352</a>
<a href=#353 id=353 data-nosnippet>353</a> <span class="doccomment">/// Returns the length, in bytes, of the shortest pattern added.
<a href=#354 id=354 data-nosnippet>354</a> </span><span class="kw">pub fn </span>minimum_len(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; usize {
<a href=#355 id=355 data-nosnippet>355</a> <span class="self">self</span>.patterns.minimum_len()
<a href=#356 id=356 data-nosnippet>356</a> }
<a href=#357 id=357 data-nosnippet>357</a>}
<a href=#358 id=358 data-nosnippet>358</a>
<a href=#359 id=359 data-nosnippet>359</a><span class="kw">impl </span>Default <span class="kw">for </span>Builder {
<a href=#360 id=360 data-nosnippet>360</a> <span class="kw">fn </span>default() -&gt; Builder {
<a href=#361 id=361 data-nosnippet>361</a> Builder::new()
<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>
<a href=#365 id=365 data-nosnippet>365</a><span class="doccomment">/// A packed searcher for quickly finding occurrences of multiple patterns.
<a href=#366 id=366 data-nosnippet>366</a>///
<a href=#367 id=367 data-nosnippet>367</a>/// If callers need more flexible construction, or if one wants to change the
<a href=#368 id=368 data-nosnippet>368</a>/// match semantics (either leftmost-first or leftmost-longest), then one can
<a href=#369 id=369 data-nosnippet>369</a>/// use the [`Config`] and/or [`Builder`] types for more fine grained control.
<a href=#370 id=370 data-nosnippet>370</a>///
<a href=#371 id=371 data-nosnippet>371</a>/// # Example
<a href=#372 id=372 data-nosnippet>372</a>///
<a href=#373 id=373 data-nosnippet>373</a>/// This example shows how to create a searcher from an iterator of patterns.
<a href=#374 id=374 data-nosnippet>374</a>/// By default, leftmost-first match semantics are used.
<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>/// use aho_corasick::{packed::{MatchKind, Searcher}, PatternID};
<a href=#378 id=378 data-nosnippet>378</a>///
<a href=#379 id=379 data-nosnippet>379</a>/// # fn example() -&gt; Option&lt;()&gt; {
<a href=#380 id=380 data-nosnippet>380</a>/// let searcher = Searcher::new(["foobar", "foo"].iter().cloned())?;
<a href=#381 id=381 data-nosnippet>381</a>/// let matches: Vec&lt;PatternID&gt; = searcher
<a href=#382 id=382 data-nosnippet>382</a>/// .find_iter("foobar")
<a href=#383 id=383 data-nosnippet>383</a>/// .map(|mat| mat.pattern())
<a href=#384 id=384 data-nosnippet>384</a>/// .collect();
<a href=#385 id=385 data-nosnippet>385</a>/// assert_eq!(vec![PatternID::ZERO], matches);
<a href=#386 id=386 data-nosnippet>386</a>/// # Some(()) }
<a href=#387 id=387 data-nosnippet>387</a>/// # if cfg!(all(feature = "std", any(
<a href=#388 id=388 data-nosnippet>388</a>/// # target_arch = "x86_64", target_arch = "aarch64",
<a href=#389 id=389 data-nosnippet>389</a>/// # ))) {
<a href=#390 id=390 data-nosnippet>390</a>/// # example().unwrap()
<a href=#391 id=391 data-nosnippet>391</a>/// # } else {
<a href=#392 id=392 data-nosnippet>392</a>/// # assert!(example().is_none());
<a href=#393 id=393 data-nosnippet>393</a>/// # }
<a href=#394 id=394 data-nosnippet>394</a>/// ```
<a href=#395 id=395 data-nosnippet>395</a></span><span class="attr">#[derive(Clone, Debug)]
<a href=#396 id=396 data-nosnippet>396</a></span><span class="kw">pub struct </span>Searcher {
<a href=#397 id=397 data-nosnippet>397</a> patterns: Arc&lt;Patterns&gt;,
<a href=#398 id=398 data-nosnippet>398</a> rabinkarp: RabinKarp,
<a href=#399 id=399 data-nosnippet>399</a> search_kind: SearchKind,
<a href=#400 id=400 data-nosnippet>400</a> minimum_len: usize,
<a href=#401 id=401 data-nosnippet>401</a>}
<a href=#402 id=402 data-nosnippet>402</a>
<a href=#403 id=403 data-nosnippet>403</a><span class="attr">#[derive(Clone, Debug)]
<a href=#404 id=404 data-nosnippet>404</a></span><span class="kw">enum </span>SearchKind {
<a href=#405 id=405 data-nosnippet>405</a> Teddy(teddy::Searcher),
<a href=#406 id=406 data-nosnippet>406</a> RabinKarp,
<a href=#407 id=407 data-nosnippet>407</a>}
<a href=#408 id=408 data-nosnippet>408</a>
<a href=#409 id=409 data-nosnippet>409</a><span class="kw">impl </span>Searcher {
<a href=#410 id=410 data-nosnippet>410</a> <span class="doccomment">/// A convenience function for constructing a searcher from an iterator
<a href=#411 id=411 data-nosnippet>411</a> /// of things that can be converted to a `&amp;[u8]`.
<a href=#412 id=412 data-nosnippet>412</a> ///
<a href=#413 id=413 data-nosnippet>413</a> /// If a searcher could not be constructed (either because of an
<a href=#414 id=414 data-nosnippet>414</a> /// unsupported CPU or because there are too many patterns), then `None`
<a href=#415 id=415 data-nosnippet>415</a> /// is returned.
<a href=#416 id=416 data-nosnippet>416</a> ///
<a href=#417 id=417 data-nosnippet>417</a> /// # Example
<a href=#418 id=418 data-nosnippet>418</a> ///
<a href=#419 id=419 data-nosnippet>419</a> /// Basic usage:
<a href=#420 id=420 data-nosnippet>420</a> ///
<a href=#421 id=421 data-nosnippet>421</a> /// ```
<a href=#422 id=422 data-nosnippet>422</a> /// use aho_corasick::{packed::{MatchKind, Searcher}, PatternID};
<a href=#423 id=423 data-nosnippet>423</a> ///
<a href=#424 id=424 data-nosnippet>424</a> /// # fn example() -&gt; Option&lt;()&gt; {
<a href=#425 id=425 data-nosnippet>425</a> /// let searcher = Searcher::new(["foobar", "foo"].iter().cloned())?;
<a href=#426 id=426 data-nosnippet>426</a> /// let matches: Vec&lt;PatternID&gt; = searcher
<a href=#427 id=427 data-nosnippet>427</a> /// .find_iter("foobar")
<a href=#428 id=428 data-nosnippet>428</a> /// .map(|mat| mat.pattern())
<a href=#429 id=429 data-nosnippet>429</a> /// .collect();
<a href=#430 id=430 data-nosnippet>430</a> /// assert_eq!(vec![PatternID::ZERO], matches);
<a href=#431 id=431 data-nosnippet>431</a> /// # Some(()) }
<a href=#432 id=432 data-nosnippet>432</a> /// # if cfg!(all(feature = "std", any(
<a href=#433 id=433 data-nosnippet>433</a> /// # target_arch = "x86_64", target_arch = "aarch64",
<a href=#434 id=434 data-nosnippet>434</a> /// # ))) {
<a href=#435 id=435 data-nosnippet>435</a> /// # example().unwrap()
<a href=#436 id=436 data-nosnippet>436</a> /// # } else {
<a href=#437 id=437 data-nosnippet>437</a> /// # assert!(example().is_none());
<a href=#438 id=438 data-nosnippet>438</a> /// # }
<a href=#439 id=439 data-nosnippet>439</a> /// ```
<a href=#440 id=440 data-nosnippet>440</a> </span><span class="kw">pub fn </span>new&lt;I, P&gt;(patterns: I) -&gt; <span class="prelude-ty">Option</span>&lt;Searcher&gt;
<a href=#441 id=441 data-nosnippet>441</a> <span class="kw">where
<a href=#442 id=442 data-nosnippet>442</a> </span>I: IntoIterator&lt;Item = P&gt;,
<a href=#443 id=443 data-nosnippet>443</a> P: AsRef&lt;[u8]&gt;,
<a href=#444 id=444 data-nosnippet>444</a> {
<a href=#445 id=445 data-nosnippet>445</a> Builder::new().extend(patterns).build()
<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">/// A convenience function for calling `Config::new()`.
<a href=#449 id=449 data-nosnippet>449</a> ///
<a href=#450 id=450 data-nosnippet>450</a> /// This is useful for avoiding an additional import.
<a href=#451 id=451 data-nosnippet>451</a> </span><span class="kw">pub fn </span>config() -&gt; Config {
<a href=#452 id=452 data-nosnippet>452</a> Config::new()
<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">/// A convenience function for calling `Builder::new()`.
<a href=#456 id=456 data-nosnippet>456</a> ///
<a href=#457 id=457 data-nosnippet>457</a> /// This is useful for avoiding an additional import.
<a href=#458 id=458 data-nosnippet>458</a> </span><span class="kw">pub fn </span>builder() -&gt; Builder {
<a href=#459 id=459 data-nosnippet>459</a> Builder::new()
<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 first occurrence of any of the patterns in this searcher,
<a href=#463 id=463 data-nosnippet>463</a> /// according to its match semantics, in the given haystack. The `Match`
<a href=#464 id=464 data-nosnippet>464</a> /// returned will include the identifier of the pattern that matched, which
<a href=#465 id=465 data-nosnippet>465</a> /// corresponds to the index of the pattern (starting from `0`) in which it
<a href=#466 id=466 data-nosnippet>466</a> /// was added.
<a href=#467 id=467 data-nosnippet>467</a> ///
<a href=#468 id=468 data-nosnippet>468</a> /// # Example
<a href=#469 id=469 data-nosnippet>469</a> ///
<a href=#470 id=470 data-nosnippet>470</a> /// Basic usage:
<a href=#471 id=471 data-nosnippet>471</a> ///
<a href=#472 id=472 data-nosnippet>472</a> /// ```
<a href=#473 id=473 data-nosnippet>473</a> /// use aho_corasick::{packed::{MatchKind, Searcher}, PatternID};
<a href=#474 id=474 data-nosnippet>474</a> ///
<a href=#475 id=475 data-nosnippet>475</a> /// # fn example() -&gt; Option&lt;()&gt; {
<a href=#476 id=476 data-nosnippet>476</a> /// let searcher = Searcher::new(["foobar", "foo"].iter().cloned())?;
<a href=#477 id=477 data-nosnippet>477</a> /// let mat = searcher.find("foobar")?;
<a href=#478 id=478 data-nosnippet>478</a> /// assert_eq!(PatternID::ZERO, mat.pattern());
<a href=#479 id=479 data-nosnippet>479</a> /// assert_eq!(0, mat.start());
<a href=#480 id=480 data-nosnippet>480</a> /// assert_eq!(6, mat.end());
<a href=#481 id=481 data-nosnippet>481</a> /// # Some(()) }
<a href=#482 id=482 data-nosnippet>482</a> /// # if cfg!(all(feature = "std", any(
<a href=#483 id=483 data-nosnippet>483</a> /// # target_arch = "x86_64", target_arch = "aarch64",
<a href=#484 id=484 data-nosnippet>484</a> /// # ))) {
<a href=#485 id=485 data-nosnippet>485</a> /// # example().unwrap()
<a href=#486 id=486 data-nosnippet>486</a> /// # } else {
<a href=#487 id=487 data-nosnippet>487</a> /// # assert!(example().is_none());
<a href=#488 id=488 data-nosnippet>488</a> /// # }
<a href=#489 id=489 data-nosnippet>489</a> /// ```
<a href=#490 id=490 data-nosnippet>490</a> </span><span class="attr">#[inline]
<a href=#491 id=491 data-nosnippet>491</a> </span><span class="kw">pub fn </span>find&lt;B: AsRef&lt;[u8]&gt;&gt;(<span class="kw-2">&amp;</span><span class="self">self</span>, haystack: B) -&gt; <span class="prelude-ty">Option</span>&lt;Match&gt; {
<a href=#492 id=492 data-nosnippet>492</a> <span class="kw">let </span>haystack = haystack.as_ref();
<a href=#493 id=493 data-nosnippet>493</a> <span class="self">self</span>.find_in(haystack, Span::from(<span class="number">0</span>..haystack.len()))
<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">/// Return the first occurrence of any of the patterns in this searcher,
<a href=#497 id=497 data-nosnippet>497</a> /// according to its match semantics, in the given haystack starting from
<a href=#498 id=498 data-nosnippet>498</a> /// the given position.
<a href=#499 id=499 data-nosnippet>499</a> ///
<a href=#500 id=500 data-nosnippet>500</a> /// The `Match` returned will include the identifier of the pattern that
<a href=#501 id=501 data-nosnippet>501</a> /// matched, which corresponds to the index of the pattern (starting from
<a href=#502 id=502 data-nosnippet>502</a> /// `0`) in which it was added. The offsets in the `Match` will be relative
<a href=#503 id=503 data-nosnippet>503</a> /// to the start of `haystack` (and not `at`).
<a href=#504 id=504 data-nosnippet>504</a> ///
<a href=#505 id=505 data-nosnippet>505</a> /// # Example
<a href=#506 id=506 data-nosnippet>506</a> ///
<a href=#507 id=507 data-nosnippet>507</a> /// Basic usage:
<a href=#508 id=508 data-nosnippet>508</a> ///
<a href=#509 id=509 data-nosnippet>509</a> /// ```
<a href=#510 id=510 data-nosnippet>510</a> /// use aho_corasick::{packed::{MatchKind, Searcher}, PatternID, Span};
<a href=#511 id=511 data-nosnippet>511</a> ///
<a href=#512 id=512 data-nosnippet>512</a> /// # fn example() -&gt; Option&lt;()&gt; {
<a href=#513 id=513 data-nosnippet>513</a> /// let haystack = "foofoobar";
<a href=#514 id=514 data-nosnippet>514</a> /// let searcher = Searcher::new(["foobar", "foo"].iter().cloned())?;
<a href=#515 id=515 data-nosnippet>515</a> /// let mat = searcher.find_in(haystack, Span::from(3..haystack.len()))?;
<a href=#516 id=516 data-nosnippet>516</a> /// assert_eq!(PatternID::ZERO, mat.pattern());
<a href=#517 id=517 data-nosnippet>517</a> /// assert_eq!(3, mat.start());
<a href=#518 id=518 data-nosnippet>518</a> /// assert_eq!(9, mat.end());
<a href=#519 id=519 data-nosnippet>519</a> /// # Some(()) }
<a href=#520 id=520 data-nosnippet>520</a> /// # if cfg!(all(feature = "std", any(
<a href=#521 id=521 data-nosnippet>521</a> /// # target_arch = "x86_64", target_arch = "aarch64",
<a href=#522 id=522 data-nosnippet>522</a> /// # ))) {
<a href=#523 id=523 data-nosnippet>523</a> /// # example().unwrap()
<a href=#524 id=524 data-nosnippet>524</a> /// # } else {
<a href=#525 id=525 data-nosnippet>525</a> /// # assert!(example().is_none());
<a href=#526 id=526 data-nosnippet>526</a> /// # }
<a href=#527 id=527 data-nosnippet>527</a> /// ```
<a href=#528 id=528 data-nosnippet>528</a> </span><span class="attr">#[inline]
<a href=#529 id=529 data-nosnippet>529</a> </span><span class="kw">pub fn </span>find_in&lt;B: AsRef&lt;[u8]&gt;&gt;(
<a href=#530 id=530 data-nosnippet>530</a> <span class="kw-2">&amp;</span><span class="self">self</span>,
<a href=#531 id=531 data-nosnippet>531</a> haystack: B,
<a href=#532 id=532 data-nosnippet>532</a> span: Span,
<a href=#533 id=533 data-nosnippet>533</a> ) -&gt; <span class="prelude-ty">Option</span>&lt;Match&gt; {
<a href=#534 id=534 data-nosnippet>534</a> <span class="kw">let </span>haystack = haystack.as_ref();
<a href=#535 id=535 data-nosnippet>535</a> <span class="kw">match </span><span class="self">self</span>.search_kind {
<a href=#536 id=536 data-nosnippet>536</a> SearchKind::Teddy(<span class="kw-2">ref </span>teddy) =&gt; {
<a href=#537 id=537 data-nosnippet>537</a> <span class="kw">if </span>haystack[span].len() &lt; teddy.minimum_len() {
<a href=#538 id=538 data-nosnippet>538</a> <span class="kw">return </span><span class="self">self</span>.find_in_slow(haystack, span);
<a href=#539 id=539 data-nosnippet>539</a> }
<a href=#540 id=540 data-nosnippet>540</a> teddy.find(<span class="kw-2">&amp;</span>haystack[..span.end], span.start)
<a href=#541 id=541 data-nosnippet>541</a> }
<a href=#542 id=542 data-nosnippet>542</a> SearchKind::RabinKarp =&gt; {
<a href=#543 id=543 data-nosnippet>543</a> <span class="self">self</span>.rabinkarp.find_at(<span class="kw-2">&amp;</span>haystack[..span.end], span.start)
<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>
<a href=#548 id=548 data-nosnippet>548</a> <span class="doccomment">/// Return an iterator of non-overlapping occurrences of the patterns in
<a href=#549 id=549 data-nosnippet>549</a> /// this searcher, according to its match semantics, in the given haystack.
<a href=#550 id=550 data-nosnippet>550</a> ///
<a href=#551 id=551 data-nosnippet>551</a> /// # Example
<a href=#552 id=552 data-nosnippet>552</a> ///
<a href=#553 id=553 data-nosnippet>553</a> /// Basic usage:
<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> /// use aho_corasick::{packed::{MatchKind, Searcher}, PatternID};
<a href=#557 id=557 data-nosnippet>557</a> ///
<a href=#558 id=558 data-nosnippet>558</a> /// # fn example() -&gt; Option&lt;()&gt; {
<a href=#559 id=559 data-nosnippet>559</a> /// let searcher = Searcher::new(["foobar", "foo"].iter().cloned())?;
<a href=#560 id=560 data-nosnippet>560</a> /// let matches: Vec&lt;PatternID&gt; = searcher
<a href=#561 id=561 data-nosnippet>561</a> /// .find_iter("foobar fooba foofoo")
<a href=#562 id=562 data-nosnippet>562</a> /// .map(|mat| mat.pattern())
<a href=#563 id=563 data-nosnippet>563</a> /// .collect();
<a href=#564 id=564 data-nosnippet>564</a> /// assert_eq!(vec![
<a href=#565 id=565 data-nosnippet>565</a> /// PatternID::must(0),
<a href=#566 id=566 data-nosnippet>566</a> /// PatternID::must(1),
<a href=#567 id=567 data-nosnippet>567</a> /// PatternID::must(1),
<a href=#568 id=568 data-nosnippet>568</a> /// PatternID::must(1),
<a href=#569 id=569 data-nosnippet>569</a> /// ], matches);
<a href=#570 id=570 data-nosnippet>570</a> /// # Some(()) }
<a href=#571 id=571 data-nosnippet>571</a> /// # if cfg!(all(feature = "std", any(
<a href=#572 id=572 data-nosnippet>572</a> /// # target_arch = "x86_64", target_arch = "aarch64",
<a href=#573 id=573 data-nosnippet>573</a> /// # ))) {
<a href=#574 id=574 data-nosnippet>574</a> /// # example().unwrap()
<a href=#575 id=575 data-nosnippet>575</a> /// # } else {
<a href=#576 id=576 data-nosnippet>576</a> /// # assert!(example().is_none());
<a href=#577 id=577 data-nosnippet>577</a> /// # }
<a href=#578 id=578 data-nosnippet>578</a> /// ```
<a href=#579 id=579 data-nosnippet>579</a> </span><span class="attr">#[inline]
<a href=#580 id=580 data-nosnippet>580</a> </span><span class="kw">pub fn </span>find_iter&lt;<span class="lifetime">'a</span>, <span class="lifetime">'b</span>, B: <span class="question-mark">?</span>Sized + AsRef&lt;[u8]&gt;&gt;(
<a href=#581 id=581 data-nosnippet>581</a> <span class="kw-2">&amp;</span><span class="lifetime">'a </span><span class="self">self</span>,
<a href=#582 id=582 data-nosnippet>582</a> haystack: <span class="kw-2">&amp;</span><span class="lifetime">'b </span>B,
<a href=#583 id=583 data-nosnippet>583</a> ) -&gt; FindIter&lt;<span class="lifetime">'a</span>, <span class="lifetime">'b</span>&gt; {
<a href=#584 id=584 data-nosnippet>584</a> <span class="kw">let </span>haystack = haystack.as_ref();
<a href=#585 id=585 data-nosnippet>585</a> <span class="kw">let </span>span = Span::from(<span class="number">0</span>..haystack.len());
<a href=#586 id=586 data-nosnippet>586</a> FindIter { searcher: <span class="self">self</span>, haystack, span }
<a href=#587 id=587 data-nosnippet>587</a> }
<a href=#588 id=588 data-nosnippet>588</a>
<a href=#589 id=589 data-nosnippet>589</a> <span class="doccomment">/// Returns the match kind used by this packed searcher.
<a href=#590 id=590 data-nosnippet>590</a> ///
<a href=#591 id=591 data-nosnippet>591</a> /// # Examples
<a href=#592 id=592 data-nosnippet>592</a> ///
<a href=#593 id=593 data-nosnippet>593</a> /// Basic usage:
<a href=#594 id=594 data-nosnippet>594</a> ///
<a href=#595 id=595 data-nosnippet>595</a> /// ```
<a href=#596 id=596 data-nosnippet>596</a> /// use aho_corasick::packed::{MatchKind, Searcher};
<a href=#597 id=597 data-nosnippet>597</a> ///
<a href=#598 id=598 data-nosnippet>598</a> /// # fn example() -&gt; Option&lt;()&gt; {
<a href=#599 id=599 data-nosnippet>599</a> /// let searcher = Searcher::new(["foobar", "foo"].iter().cloned())?;
<a href=#600 id=600 data-nosnippet>600</a> /// // leftmost-first is the default.
<a href=#601 id=601 data-nosnippet>601</a> /// assert_eq!(&amp;MatchKind::LeftmostFirst, searcher.match_kind());
<a href=#602 id=602 data-nosnippet>602</a> /// # Some(()) }
<a href=#603 id=603 data-nosnippet>603</a> /// # if cfg!(all(feature = "std", any(
<a href=#604 id=604 data-nosnippet>604</a> /// # target_arch = "x86_64", target_arch = "aarch64",
<a href=#605 id=605 data-nosnippet>605</a> /// # ))) {
<a href=#606 id=606 data-nosnippet>606</a> /// # example().unwrap()
<a href=#607 id=607 data-nosnippet>607</a> /// # } else {
<a href=#608 id=608 data-nosnippet>608</a> /// # assert!(example().is_none());
<a href=#609 id=609 data-nosnippet>609</a> /// # }
<a href=#610 id=610 data-nosnippet>610</a> /// ```
<a href=#611 id=611 data-nosnippet>611</a> </span><span class="attr">#[inline]
<a href=#612 id=612 data-nosnippet>612</a> </span><span class="kw">pub fn </span>match_kind(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; <span class="kw-2">&amp;</span>MatchKind {
<a href=#613 id=613 data-nosnippet>613</a> <span class="self">self</span>.patterns.match_kind()
<a href=#614 id=614 data-nosnippet>614</a> }
<a href=#615 id=615 data-nosnippet>615</a>
<a href=#616 id=616 data-nosnippet>616</a> <span class="doccomment">/// Returns the minimum length of a haystack that is required in order for
<a href=#617 id=617 data-nosnippet>617</a> /// packed searching to be effective.
<a href=#618 id=618 data-nosnippet>618</a> ///
<a href=#619 id=619 data-nosnippet>619</a> /// In some cases, the underlying packed searcher may not be able to search
<a href=#620 id=620 data-nosnippet>620</a> /// very short haystacks. When that occurs, the implementation will defer
<a href=#621 id=621 data-nosnippet>621</a> /// to a slower non-packed searcher (which is still generally faster than
<a href=#622 id=622 data-nosnippet>622</a> /// Aho-Corasick for a small number of patterns). However, callers may
<a href=#623 id=623 data-nosnippet>623</a> /// want to avoid ever using the slower variant, which one can do by
<a href=#624 id=624 data-nosnippet>624</a> /// never passing a haystack shorter than the minimum length returned by
<a href=#625 id=625 data-nosnippet>625</a> /// this method.
<a href=#626 id=626 data-nosnippet>626</a> </span><span class="attr">#[inline]
<a href=#627 id=627 data-nosnippet>627</a> </span><span class="kw">pub fn </span>minimum_len(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; usize {
<a href=#628 id=628 data-nosnippet>628</a> <span class="self">self</span>.minimum_len
<a href=#629 id=629 data-nosnippet>629</a> }
<a href=#630 id=630 data-nosnippet>630</a>
<a href=#631 id=631 data-nosnippet>631</a> <span class="doccomment">/// Returns the approximate total amount of heap used by this searcher, in
<a href=#632 id=632 data-nosnippet>632</a> /// units of bytes.
<a href=#633 id=633 data-nosnippet>633</a> </span><span class="attr">#[inline]
<a href=#634 id=634 data-nosnippet>634</a> </span><span class="kw">pub fn </span>memory_usage(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; usize {
<a href=#635 id=635 data-nosnippet>635</a> <span class="self">self</span>.patterns.memory_usage()
<a href=#636 id=636 data-nosnippet>636</a> + <span class="self">self</span>.rabinkarp.memory_usage()
<a href=#637 id=637 data-nosnippet>637</a> + <span class="self">self</span>.search_kind.memory_usage()
<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="doccomment">/// Use a slow (non-packed) searcher.
<a href=#641 id=641 data-nosnippet>641</a> ///
<a href=#642 id=642 data-nosnippet>642</a> /// This is useful when a packed searcher could be constructed, but could
<a href=#643 id=643 data-nosnippet>643</a> /// not be used to search a specific haystack. For example, if Teddy was
<a href=#644 id=644 data-nosnippet>644</a> /// built but the haystack is smaller than ~34 bytes, then Teddy might not
<a href=#645 id=645 data-nosnippet>645</a> /// be able to run.
<a href=#646 id=646 data-nosnippet>646</a> </span><span class="kw">fn </span>find_in_slow(<span class="kw-2">&amp;</span><span class="self">self</span>, haystack: <span class="kw-2">&amp;</span>[u8], span: Span) -&gt; <span class="prelude-ty">Option</span>&lt;Match&gt; {
<a href=#647 id=647 data-nosnippet>647</a> <span class="self">self</span>.rabinkarp.find_at(<span class="kw-2">&amp;</span>haystack[..span.end], span.start)
<a href=#648 id=648 data-nosnippet>648</a> }
<a href=#649 id=649 data-nosnippet>649</a>}
<a href=#650 id=650 data-nosnippet>650</a>
<a href=#651 id=651 data-nosnippet>651</a><span class="kw">impl </span>SearchKind {
<a href=#652 id=652 data-nosnippet>652</a> <span class="kw">fn </span>memory_usage(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; usize {
<a href=#653 id=653 data-nosnippet>653</a> <span class="kw">match </span><span class="kw-2">*</span><span class="self">self </span>{
<a href=#654 id=654 data-nosnippet>654</a> SearchKind::Teddy(<span class="kw-2">ref </span>ted) =&gt; ted.memory_usage(),
<a href=#655 id=655 data-nosnippet>655</a> SearchKind::RabinKarp =&gt; <span class="number">0</span>,
<a href=#656 id=656 data-nosnippet>656</a> }
<a href=#657 id=657 data-nosnippet>657</a> }
<a href=#658 id=658 data-nosnippet>658</a>}
<a href=#659 id=659 data-nosnippet>659</a>
<a href=#660 id=660 data-nosnippet>660</a><span class="doccomment">/// An iterator over non-overlapping matches from a packed searcher.
<a href=#661 id=661 data-nosnippet>661</a>///
<a href=#662 id=662 data-nosnippet>662</a>/// The lifetime `'s` refers to the lifetime of the underlying [`Searcher`],
<a href=#663 id=663 data-nosnippet>663</a>/// while the lifetime `'h` refers to the lifetime of the haystack being
<a href=#664 id=664 data-nosnippet>664</a>/// searched.
<a href=#665 id=665 data-nosnippet>665</a></span><span class="attr">#[derive(Debug)]
<a href=#666 id=666 data-nosnippet>666</a></span><span class="kw">pub struct </span>FindIter&lt;<span class="lifetime">'s</span>, <span class="lifetime">'h</span>&gt; {
<a href=#667 id=667 data-nosnippet>667</a> searcher: <span class="kw-2">&amp;</span><span class="lifetime">'s </span>Searcher,
<a href=#668 id=668 data-nosnippet>668</a> haystack: <span class="kw-2">&amp;</span><span class="lifetime">'h </span>[u8],
<a href=#669 id=669 data-nosnippet>669</a> span: Span,
<a href=#670 id=670 data-nosnippet>670</a>}
<a href=#671 id=671 data-nosnippet>671</a>
<a href=#672 id=672 data-nosnippet>672</a><span class="kw">impl</span>&lt;<span class="lifetime">'s</span>, <span class="lifetime">'h</span>&gt; Iterator <span class="kw">for </span>FindIter&lt;<span class="lifetime">'s</span>, <span class="lifetime">'h</span>&gt; {
<a href=#673 id=673 data-nosnippet>673</a> <span class="kw">type </span>Item = Match;
<a href=#674 id=674 data-nosnippet>674</a>
<a href=#675 id=675 data-nosnippet>675</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;Match&gt; {
<a href=#676 id=676 data-nosnippet>676</a> <span class="kw">if </span><span class="self">self</span>.span.start &gt; <span class="self">self</span>.span.end {
<a href=#677 id=677 data-nosnippet>677</a> <span class="kw">return </span><span class="prelude-val">None</span>;
<a href=#678 id=678 data-nosnippet>678</a> }
<a href=#679 id=679 data-nosnippet>679</a> <span class="kw">match </span><span class="self">self</span>.searcher.find_in(<span class="self">self</span>.haystack, <span class="self">self</span>.span) {
<a href=#680 id=680 data-nosnippet>680</a> <span class="prelude-val">None </span>=&gt; <span class="prelude-val">None</span>,
<a href=#681 id=681 data-nosnippet>681</a> <span class="prelude-val">Some</span>(m) =&gt; {
<a href=#682 id=682 data-nosnippet>682</a> <span class="self">self</span>.span.start = m.end();
<a href=#683 id=683 data-nosnippet>683</a> <span class="prelude-val">Some</span>(m)
<a href=#684 id=684 data-nosnippet>684</a> }
<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>}
</code></pre></div></section></main></body></html>

View File

@@ -0,0 +1,40 @@
<!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/packed/ext.rs`."><title>ext.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/packed/</div>ext.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 trait for adding some helper routines to pointers.
<a href=#2 id=2 data-nosnippet>2</a></span><span class="kw">pub</span>(<span class="kw">crate</span>) <span class="kw">trait </span>Pointer {
<a href=#3 id=3 data-nosnippet>3</a> <span class="doccomment">/// Returns the distance, in units of `T`, between `self` and `origin`.
<a href=#4 id=4 data-nosnippet>4</a> ///
<a href=#5 id=5 data-nosnippet>5</a> /// # Safety
<a href=#6 id=6 data-nosnippet>6</a> ///
<a href=#7 id=7 data-nosnippet>7</a> /// Same as `ptr::offset_from` in addition to `self &gt;= origin`.
<a href=#8 id=8 data-nosnippet>8</a> </span><span class="kw">unsafe fn </span>distance(<span class="self">self</span>, origin: <span class="self">Self</span>) -&gt; usize;
<a href=#9 id=9 data-nosnippet>9</a>
<a href=#10 id=10 data-nosnippet>10</a> <span class="doccomment">/// Casts this pointer to `usize`.
<a href=#11 id=11 data-nosnippet>11</a> ///
<a href=#12 id=12 data-nosnippet>12</a> /// Callers should not convert the `usize` back to a pointer if at all
<a href=#13 id=13 data-nosnippet>13</a> /// possible. (And if you believe it's necessary, open an issue to discuss
<a href=#14 id=14 data-nosnippet>14</a> /// why. Otherwise, it has the potential to violate pointer provenance.)
<a href=#15 id=15 data-nosnippet>15</a> /// The purpose of this function is just to be able to do arithmetic, i.e.,
<a href=#16 id=16 data-nosnippet>16</a> /// computing offsets or alignments.
<a href=#17 id=17 data-nosnippet>17</a> </span><span class="kw">fn </span>as_usize(<span class="self">self</span>) -&gt; usize;
<a href=#18 id=18 data-nosnippet>18</a>}
<a href=#19 id=19 data-nosnippet>19</a>
<a href=#20 id=20 data-nosnippet>20</a><span class="kw">impl</span>&lt;T&gt; Pointer <span class="kw">for </span><span class="kw-2">*const </span>T {
<a href=#21 id=21 data-nosnippet>21</a> <span class="kw">unsafe fn </span>distance(<span class="self">self</span>, origin: <span class="kw-2">*const </span>T) -&gt; usize {
<a href=#22 id=22 data-nosnippet>22</a> <span class="comment">// TODO: Replace with `ptr::sub_ptr` once stabilized.
<a href=#23 id=23 data-nosnippet>23</a> </span>usize::try_from(<span class="self">self</span>.offset_from(origin)).unwrap_unchecked()
<a href=#24 id=24 data-nosnippet>24</a> }
<a href=#25 id=25 data-nosnippet>25</a>
<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> <span class="self">self </span><span class="kw">as </span>usize
<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>
<a href=#31 id=31 data-nosnippet>31</a><span class="kw">impl</span>&lt;T&gt; Pointer <span class="kw">for </span><span class="kw-2">*mut </span>T {
<a href=#32 id=32 data-nosnippet>32</a> <span class="kw">unsafe fn </span>distance(<span class="self">self</span>, origin: <span class="kw-2">*mut </span>T) -&gt; usize {
<a href=#33 id=33 data-nosnippet>33</a> (<span class="self">self </span><span class="kw">as </span><span class="kw-2">*const </span>T).distance(origin <span class="kw">as </span><span class="kw-2">*const </span>T)
<a href=#34 id=34 data-nosnippet>34</a> }
<a href=#35 id=35 data-nosnippet>35</a>
<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="self">self </span><span class="kw">as </span><span class="kw-2">*const </span>T).as_usize()
<a href=#38 id=38 data-nosnippet>38</a> }
<a href=#39 id=39 data-nosnippet>39</a>}
</code></pre></div></section></main></body></html>

View File

@@ -0,0 +1,121 @@
<!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/packed/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/packed/</div>mod.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>Provides packed multiple substring search, principally for a small number of
<a href=#3 id=3 data-nosnippet>3</a>patterns.
<a href=#4 id=4 data-nosnippet>4</a>
<a href=#5 id=5 data-nosnippet>5</a>This sub-module provides vectorized routines for quickly finding
<a href=#6 id=6 data-nosnippet>6</a>matches of a small number of patterns. In general, users of this crate
<a href=#7 id=7 data-nosnippet>7</a>shouldn't need to interface with this module directly, as the primary
<a href=#8 id=8 data-nosnippet>8</a>[`AhoCorasick`](crate::AhoCorasick) searcher will use these routines
<a href=#9 id=9 data-nosnippet>9</a>automatically as a prefilter when applicable. However, in some cases, callers
<a href=#10 id=10 data-nosnippet>10</a>may want to bypass the Aho-Corasick machinery entirely and use this vectorized
<a href=#11 id=11 data-nosnippet>11</a>searcher directly.
<a href=#12 id=12 data-nosnippet>12</a>
<a href=#13 id=13 data-nosnippet>13</a># Overview
<a href=#14 id=14 data-nosnippet>14</a>
<a href=#15 id=15 data-nosnippet>15</a>The primary types in this sub-module are:
<a href=#16 id=16 data-nosnippet>16</a>
<a href=#17 id=17 data-nosnippet>17</a>* [`Searcher`] executes the actual search algorithm to report matches in a
<a href=#18 id=18 data-nosnippet>18</a>haystack.
<a href=#19 id=19 data-nosnippet>19</a>* [`Builder`] accumulates patterns incrementally and can construct a
<a href=#20 id=20 data-nosnippet>20</a>`Searcher`.
<a href=#21 id=21 data-nosnippet>21</a>* [`Config`] permits tuning the searcher, and itself will produce a `Builder`
<a href=#22 id=22 data-nosnippet>22</a>(which can then be used to build a `Searcher`). Currently, the only tuneable
<a href=#23 id=23 data-nosnippet>23</a>knob are the match semantics, but this may be expanded in the future.
<a href=#24 id=24 data-nosnippet>24</a>
<a href=#25 id=25 data-nosnippet>25</a># Examples
<a href=#26 id=26 data-nosnippet>26</a>
<a href=#27 id=27 data-nosnippet>27</a>This example shows how to create a searcher from an iterator of patterns.
<a href=#28 id=28 data-nosnippet>28</a>By default, leftmost-first match semantics are used. (See the top-level
<a href=#29 id=29 data-nosnippet>29</a>[`MatchKind`] type for more details about match semantics, which apply
<a href=#30 id=30 data-nosnippet>30</a>similarly to packed substring search.)
<a href=#31 id=31 data-nosnippet>31</a>
<a href=#32 id=32 data-nosnippet>32</a>```
<a href=#33 id=33 data-nosnippet>33</a>use aho_corasick::{packed::{MatchKind, Searcher}, PatternID};
<a href=#34 id=34 data-nosnippet>34</a>
<a href=#35 id=35 data-nosnippet>35</a># fn example() -&gt; Option&lt;()&gt; {
<a href=#36 id=36 data-nosnippet>36</a>let searcher = Searcher::new(["foobar", "foo"].iter().cloned())?;
<a href=#37 id=37 data-nosnippet>37</a>let matches: Vec&lt;PatternID&gt; = searcher
<a href=#38 id=38 data-nosnippet>38</a> .find_iter("foobar")
<a href=#39 id=39 data-nosnippet>39</a> .map(|mat| mat.pattern())
<a href=#40 id=40 data-nosnippet>40</a> .collect();
<a href=#41 id=41 data-nosnippet>41</a>assert_eq!(vec![PatternID::ZERO], matches);
<a href=#42 id=42 data-nosnippet>42</a># Some(()) }
<a href=#43 id=43 data-nosnippet>43</a># if cfg!(all(feature = "std", any(
<a href=#44 id=44 data-nosnippet>44</a># target_arch = "x86_64", target_arch = "aarch64",
<a href=#45 id=45 data-nosnippet>45</a># ))) {
<a href=#46 id=46 data-nosnippet>46</a># example().unwrap()
<a href=#47 id=47 data-nosnippet>47</a># } else {
<a href=#48 id=48 data-nosnippet>48</a># assert!(example().is_none());
<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>
<a href=#52 id=52 data-nosnippet>52</a>This example shows how to use [`Config`] to change the match semantics to
<a href=#53 id=53 data-nosnippet>53</a>leftmost-longest:
<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>use aho_corasick::{packed::{Config, MatchKind}, PatternID};
<a href=#57 id=57 data-nosnippet>57</a>
<a href=#58 id=58 data-nosnippet>58</a># fn example() -&gt; Option&lt;()&gt; {
<a href=#59 id=59 data-nosnippet>59</a>let searcher = Config::new()
<a href=#60 id=60 data-nosnippet>60</a> .match_kind(MatchKind::LeftmostLongest)
<a href=#61 id=61 data-nosnippet>61</a> .builder()
<a href=#62 id=62 data-nosnippet>62</a> .add("foo")
<a href=#63 id=63 data-nosnippet>63</a> .add("foobar")
<a href=#64 id=64 data-nosnippet>64</a> .build()?;
<a href=#65 id=65 data-nosnippet>65</a>let matches: Vec&lt;PatternID&gt; = searcher
<a href=#66 id=66 data-nosnippet>66</a> .find_iter("foobar")
<a href=#67 id=67 data-nosnippet>67</a> .map(|mat| mat.pattern())
<a href=#68 id=68 data-nosnippet>68</a> .collect();
<a href=#69 id=69 data-nosnippet>69</a>assert_eq!(vec![PatternID::must(1)], matches);
<a href=#70 id=70 data-nosnippet>70</a># Some(()) }
<a href=#71 id=71 data-nosnippet>71</a># if cfg!(all(feature = "std", any(
<a href=#72 id=72 data-nosnippet>72</a># target_arch = "x86_64", target_arch = "aarch64",
<a href=#73 id=73 data-nosnippet>73</a># ))) {
<a href=#74 id=74 data-nosnippet>74</a># example().unwrap()
<a href=#75 id=75 data-nosnippet>75</a># } else {
<a href=#76 id=76 data-nosnippet>76</a># assert!(example().is_none());
<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>
<a href=#80 id=80 data-nosnippet>80</a># Packed substring searching
<a href=#81 id=81 data-nosnippet>81</a>
<a href=#82 id=82 data-nosnippet>82</a>Packed substring searching refers to the use of SIMD (Single Instruction,
<a href=#83 id=83 data-nosnippet>83</a>Multiple Data) to accelerate the detection of matches in a haystack. Unlike
<a href=#84 id=84 data-nosnippet>84</a>conventional algorithms, such as Aho-Corasick, SIMD algorithms for substring
<a href=#85 id=85 data-nosnippet>85</a>search tend to do better with a small number of patterns, where as Aho-Corasick
<a href=#86 id=86 data-nosnippet>86</a>generally maintains reasonably consistent performance regardless of the number
<a href=#87 id=87 data-nosnippet>87</a>of patterns you give it. Because of this, the vectorized searcher in this
<a href=#88 id=88 data-nosnippet>88</a>sub-module cannot be used as a general purpose searcher, since building the
<a href=#89 id=89 data-nosnippet>89</a>searcher may fail even when given a small number of patterns. However, in
<a href=#90 id=90 data-nosnippet>90</a>exchange, when searching for a small number of patterns, searching can be quite
<a href=#91 id=91 data-nosnippet>91</a>a bit faster than Aho-Corasick (sometimes by an order of magnitude).
<a href=#92 id=92 data-nosnippet>92</a>
<a href=#93 id=93 data-nosnippet>93</a>The key take away here is that constructing a searcher from a list of patterns
<a href=#94 id=94 data-nosnippet>94</a>is a fallible operation with no clear rules for when it will fail. While the
<a href=#95 id=95 data-nosnippet>95</a>precise conditions under which building a searcher can fail is specifically an
<a href=#96 id=96 data-nosnippet>96</a>implementation detail, here are some common reasons:
<a href=#97 id=97 data-nosnippet>97</a>
<a href=#98 id=98 data-nosnippet>98</a>* Too many patterns were given. Typically, the limit is on the order of 100 or
<a href=#99 id=99 data-nosnippet>99</a> so, but this limit may fluctuate based on available CPU features.
<a href=#100 id=100 data-nosnippet>100</a>* The available packed algorithms require CPU features that aren't available.
<a href=#101 id=101 data-nosnippet>101</a> For example, currently, this crate only provides packed algorithms for
<a href=#102 id=102 data-nosnippet>102</a> `x86_64` and `aarch64`. Therefore, constructing a packed searcher on any
<a href=#103 id=103 data-nosnippet>103</a> other target will always fail.
<a href=#104 id=104 data-nosnippet>104</a>* Zero patterns were given, or one of the patterns given was empty. Packed
<a href=#105 id=105 data-nosnippet>105</a> searchers require at least one pattern and that all patterns are non-empty.
<a href=#106 id=106 data-nosnippet>106</a>* Something else about the nature of the patterns (typically based on
<a href=#107 id=107 data-nosnippet>107</a> heuristics) suggests that a packed searcher would perform very poorly, so
<a href=#108 id=108 data-nosnippet>108</a> no searcher is built.
<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></span><span class="kw">pub use </span><span class="kw">crate</span>::packed::api::{Builder, Config, FindIter, MatchKind, Searcher};
<a href=#112 id=112 data-nosnippet>112</a>
<a href=#113 id=113 data-nosnippet>113</a><span class="kw">mod </span>api;
<a href=#114 id=114 data-nosnippet>114</a><span class="kw">mod </span>ext;
<a href=#115 id=115 data-nosnippet>115</a><span class="kw">mod </span>pattern;
<a href=#116 id=116 data-nosnippet>116</a><span class="kw">mod </span>rabinkarp;
<a href=#117 id=117 data-nosnippet>117</a><span class="kw">mod </span>teddy;
<a href=#118 id=118 data-nosnippet>118</a><span class="attr">#[cfg(all(feature = <span class="string">"std"</span>, test))]
<a href=#119 id=119 data-nosnippet>119</a></span><span class="kw">mod </span>tests;
<a href=#120 id=120 data-nosnippet>120</a><span class="kw">mod </span>vector;
</code></pre></div></section></main></body></html>

View File

@@ -0,0 +1,481 @@
<!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/packed/pattern.rs`."><title>pattern.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/packed/</div>pattern.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::{cmp, fmt, mem, u16, usize};
<a href=#2 id=2 data-nosnippet>2</a>
<a href=#3 id=3 data-nosnippet>3</a><span class="kw">use </span>alloc::{boxed::Box, string::String, vec, vec::Vec};
<a href=#4 id=4 data-nosnippet>4</a>
<a href=#5 id=5 data-nosnippet>5</a><span class="kw">use crate</span>::{
<a href=#6 id=6 data-nosnippet>6</a> packed::{api::MatchKind, ext::Pointer},
<a href=#7 id=7 data-nosnippet>7</a> PatternID,
<a href=#8 id=8 data-nosnippet>8</a>};
<a href=#9 id=9 data-nosnippet>9</a>
<a href=#10 id=10 data-nosnippet>10</a><span class="doccomment">/// A non-empty collection of non-empty patterns to search for.
<a href=#11 id=11 data-nosnippet>11</a>///
<a href=#12 id=12 data-nosnippet>12</a>/// This collection of patterns is what is passed around to both execute
<a href=#13 id=13 data-nosnippet>13</a>/// searches and to construct the searchers themselves. Namely, this permits
<a href=#14 id=14 data-nosnippet>14</a>/// searches to avoid copying all of the patterns, and allows us to keep only
<a href=#15 id=15 data-nosnippet>15</a>/// one copy throughout all packed searchers.
<a href=#16 id=16 data-nosnippet>16</a>///
<a href=#17 id=17 data-nosnippet>17</a>/// Note that this collection is not a set. The same pattern can appear more
<a href=#18 id=18 data-nosnippet>18</a>/// than once.
<a href=#19 id=19 data-nosnippet>19</a></span><span class="attr">#[derive(Clone, Debug)]
<a href=#20 id=20 data-nosnippet>20</a></span><span class="kw">pub</span>(<span class="kw">crate</span>) <span class="kw">struct </span>Patterns {
<a href=#21 id=21 data-nosnippet>21</a> <span class="doccomment">/// The match semantics supported by this collection of patterns.
<a href=#22 id=22 data-nosnippet>22</a> ///
<a href=#23 id=23 data-nosnippet>23</a> /// The match semantics determines the order of the iterator over patterns.
<a href=#24 id=24 data-nosnippet>24</a> /// For leftmost-first, patterns are provided in the same order as were
<a href=#25 id=25 data-nosnippet>25</a> /// provided by the caller. For leftmost-longest, patterns are provided in
<a href=#26 id=26 data-nosnippet>26</a> /// descending order of length, with ties broken by the order in which they
<a href=#27 id=27 data-nosnippet>27</a> /// were provided by the caller.
<a href=#28 id=28 data-nosnippet>28</a> </span>kind: MatchKind,
<a href=#29 id=29 data-nosnippet>29</a> <span class="doccomment">/// The collection of patterns, indexed by their identifier.
<a href=#30 id=30 data-nosnippet>30</a> </span>by_id: Vec&lt;Vec&lt;u8&gt;&gt;,
<a href=#31 id=31 data-nosnippet>31</a> <span class="doccomment">/// The order of patterns defined for iteration, given by pattern
<a href=#32 id=32 data-nosnippet>32</a> /// identifiers. The order of `by_id` and `order` is always the same for
<a href=#33 id=33 data-nosnippet>33</a> /// leftmost-first semantics, but may be different for leftmost-longest
<a href=#34 id=34 data-nosnippet>34</a> /// semantics.
<a href=#35 id=35 data-nosnippet>35</a> </span>order: Vec&lt;PatternID&gt;,
<a href=#36 id=36 data-nosnippet>36</a> <span class="doccomment">/// The length of the smallest pattern, in bytes.
<a href=#37 id=37 data-nosnippet>37</a> </span>minimum_len: usize,
<a href=#38 id=38 data-nosnippet>38</a> <span class="doccomment">/// The total number of pattern bytes across the entire collection. This
<a href=#39 id=39 data-nosnippet>39</a> /// is used for reporting total heap usage in constant time.
<a href=#40 id=40 data-nosnippet>40</a> </span>total_pattern_bytes: usize,
<a href=#41 id=41 data-nosnippet>41</a>}
<a href=#42 id=42 data-nosnippet>42</a>
<a href=#43 id=43 data-nosnippet>43</a><span class="comment">// BREADCRUMBS: I think we want to experiment with a different bucket
<a href=#44 id=44 data-nosnippet>44</a>// representation. Basically, each bucket is just a Range&lt;usize&gt; to a single
<a href=#45 id=45 data-nosnippet>45</a>// contiguous allocation? Maybe length-prefixed patterns or something? The
<a href=#46 id=46 data-nosnippet>46</a>// idea is to try to get rid of the pointer chasing in verification. I don't
<a href=#47 id=47 data-nosnippet>47</a>// know that that is the issue, but I suspect it is.
<a href=#48 id=48 data-nosnippet>48</a>
<a href=#49 id=49 data-nosnippet>49</a></span><span class="kw">impl </span>Patterns {
<a href=#50 id=50 data-nosnippet>50</a> <span class="doccomment">/// Create a new collection of patterns for the given match semantics. The
<a href=#51 id=51 data-nosnippet>51</a> /// ID of each pattern is the index of the pattern at which it occurs in
<a href=#52 id=52 data-nosnippet>52</a> /// the `by_id` slice.
<a href=#53 id=53 data-nosnippet>53</a> ///
<a href=#54 id=54 data-nosnippet>54</a> /// If any of the patterns in the slice given are empty, then this panics.
<a href=#55 id=55 data-nosnippet>55</a> /// Similarly, if the number of patterns given is zero, then this also
<a href=#56 id=56 data-nosnippet>56</a> /// panics.
<a href=#57 id=57 data-nosnippet>57</a> </span><span class="kw">pub</span>(<span class="kw">crate</span>) <span class="kw">fn </span>new() -&gt; Patterns {
<a href=#58 id=58 data-nosnippet>58</a> Patterns {
<a href=#59 id=59 data-nosnippet>59</a> kind: MatchKind::default(),
<a href=#60 id=60 data-nosnippet>60</a> by_id: <span class="macro">vec!</span>[],
<a href=#61 id=61 data-nosnippet>61</a> order: <span class="macro">vec!</span>[],
<a href=#62 id=62 data-nosnippet>62</a> minimum_len: usize::MAX,
<a href=#63 id=63 data-nosnippet>63</a> total_pattern_bytes: <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>
<a href=#67 id=67 data-nosnippet>67</a> <span class="doccomment">/// Add a pattern to this collection.
<a href=#68 id=68 data-nosnippet>68</a> ///
<a href=#69 id=69 data-nosnippet>69</a> /// This panics if the pattern given is empty.
<a href=#70 id=70 data-nosnippet>70</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=#71 id=71 data-nosnippet>71</a> <span class="macro">assert!</span>(!bytes.is_empty());
<a href=#72 id=72 data-nosnippet>72</a> <span class="macro">assert!</span>(<span class="self">self</span>.by_id.len() &lt;= u16::MAX <span class="kw">as </span>usize);
<a href=#73 id=73 data-nosnippet>73</a>
<a href=#74 id=74 data-nosnippet>74</a> <span class="kw">let </span>id = PatternID::new(<span class="self">self</span>.by_id.len()).unwrap();
<a href=#75 id=75 data-nosnippet>75</a> <span class="self">self</span>.order.push(id);
<a href=#76 id=76 data-nosnippet>76</a> <span class="self">self</span>.by_id.push(bytes.to_vec());
<a href=#77 id=77 data-nosnippet>77</a> <span class="self">self</span>.minimum_len = cmp::min(<span class="self">self</span>.minimum_len, bytes.len());
<a href=#78 id=78 data-nosnippet>78</a> <span class="self">self</span>.total_pattern_bytes += bytes.len();
<a href=#79 id=79 data-nosnippet>79</a> }
<a href=#80 id=80 data-nosnippet>80</a>
<a href=#81 id=81 data-nosnippet>81</a> <span class="doccomment">/// Set the match kind semantics for this collection of patterns.
<a href=#82 id=82 data-nosnippet>82</a> ///
<a href=#83 id=83 data-nosnippet>83</a> /// If the kind is not set, then the default is leftmost-first.
<a href=#84 id=84 data-nosnippet>84</a> </span><span class="kw">pub</span>(<span class="kw">crate</span>) <span class="kw">fn </span>set_match_kind(<span class="kw-2">&amp;mut </span><span class="self">self</span>, kind: MatchKind) {
<a href=#85 id=85 data-nosnippet>85</a> <span class="self">self</span>.kind = kind;
<a href=#86 id=86 data-nosnippet>86</a> <span class="kw">match </span><span class="self">self</span>.kind {
<a href=#87 id=87 data-nosnippet>87</a> MatchKind::LeftmostFirst =&gt; {
<a href=#88 id=88 data-nosnippet>88</a> <span class="self">self</span>.order.sort();
<a href=#89 id=89 data-nosnippet>89</a> }
<a href=#90 id=90 data-nosnippet>90</a> MatchKind::LeftmostLongest =&gt; {
<a href=#91 id=91 data-nosnippet>91</a> <span class="kw">let </span>(order, by_id) = (<span class="kw-2">&amp;mut </span><span class="self">self</span>.order, <span class="kw-2">&amp;mut </span><span class="self">self</span>.by_id);
<a href=#92 id=92 data-nosnippet>92</a> order.sort_by(|<span class="kw-2">&amp;</span>id1, <span class="kw-2">&amp;</span>id2| {
<a href=#93 id=93 data-nosnippet>93</a> by_id[id1].len().cmp(<span class="kw-2">&amp;</span>by_id[id2].len()).reverse()
<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> }
<a href=#97 id=97 data-nosnippet>97</a> }
<a href=#98 id=98 data-nosnippet>98</a>
<a href=#99 id=99 data-nosnippet>99</a> <span class="doccomment">/// Return the number of patterns in this collection.
<a href=#100 id=100 data-nosnippet>100</a> ///
<a href=#101 id=101 data-nosnippet>101</a> /// This is guaranteed to be greater than zero.
<a href=#102 id=102 data-nosnippet>102</a> </span><span class="kw">pub</span>(<span class="kw">crate</span>) <span class="kw">fn </span>len(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; usize {
<a href=#103 id=103 data-nosnippet>103</a> <span class="self">self</span>.by_id.len()
<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> <span class="doccomment">/// Returns true if and only if this collection of patterns is empty.
<a href=#107 id=107 data-nosnippet>107</a> </span><span class="kw">pub</span>(<span class="kw">crate</span>) <span class="kw">fn </span>is_empty(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; bool {
<a href=#108 id=108 data-nosnippet>108</a> <span class="self">self</span>.len() == <span class="number">0
<a href=#109 id=109 data-nosnippet>109</a> </span>}
<a href=#110 id=110 data-nosnippet>110</a>
<a href=#111 id=111 data-nosnippet>111</a> <span class="doccomment">/// Returns the approximate total amount of heap used by these patterns, in
<a href=#112 id=112 data-nosnippet>112</a> /// units of bytes.
<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>memory_usage(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; usize {
<a href=#114 id=114 data-nosnippet>114</a> <span class="self">self</span>.order.len() * mem::size_of::&lt;PatternID&gt;()
<a href=#115 id=115 data-nosnippet>115</a> + <span class="self">self</span>.by_id.len() * mem::size_of::&lt;Vec&lt;u8&gt;&gt;()
<a href=#116 id=116 data-nosnippet>116</a> + <span class="self">self</span>.total_pattern_bytes
<a href=#117 id=117 data-nosnippet>117</a> }
<a href=#118 id=118 data-nosnippet>118</a>
<a href=#119 id=119 data-nosnippet>119</a> <span class="doccomment">/// Clears all heap memory associated with this collection of patterns and
<a href=#120 id=120 data-nosnippet>120</a> /// resets all state such that it is a valid empty collection.
<a href=#121 id=121 data-nosnippet>121</a> </span><span class="kw">pub</span>(<span class="kw">crate</span>) <span class="kw">fn </span>reset(<span class="kw-2">&amp;mut </span><span class="self">self</span>) {
<a href=#122 id=122 data-nosnippet>122</a> <span class="self">self</span>.kind = MatchKind::default();
<a href=#123 id=123 data-nosnippet>123</a> <span class="self">self</span>.by_id.clear();
<a href=#124 id=124 data-nosnippet>124</a> <span class="self">self</span>.order.clear();
<a href=#125 id=125 data-nosnippet>125</a> <span class="self">self</span>.minimum_len = usize::MAX;
<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">/// Returns the length, in bytes, of the smallest pattern.
<a href=#129 id=129 data-nosnippet>129</a> ///
<a href=#130 id=130 data-nosnippet>130</a> /// This is guaranteed to be at least one.
<a href=#131 id=131 data-nosnippet>131</a> </span><span class="kw">pub</span>(<span class="kw">crate</span>) <span class="kw">fn </span>minimum_len(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; usize {
<a href=#132 id=132 data-nosnippet>132</a> <span class="self">self</span>.minimum_len
<a href=#133 id=133 data-nosnippet>133</a> }
<a href=#134 id=134 data-nosnippet>134</a>
<a href=#135 id=135 data-nosnippet>135</a> <span class="doccomment">/// Returns the match semantics used by these patterns.
<a href=#136 id=136 data-nosnippet>136</a> </span><span class="kw">pub</span>(<span class="kw">crate</span>) <span class="kw">fn </span>match_kind(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; <span class="kw-2">&amp;</span>MatchKind {
<a href=#137 id=137 data-nosnippet>137</a> <span class="kw-2">&amp;</span><span class="self">self</span>.kind
<a href=#138 id=138 data-nosnippet>138</a> }
<a href=#139 id=139 data-nosnippet>139</a>
<a href=#140 id=140 data-nosnippet>140</a> <span class="doccomment">/// Return the pattern with the given identifier. If such a pattern does
<a href=#141 id=141 data-nosnippet>141</a> /// not exist, then this panics.
<a href=#142 id=142 data-nosnippet>142</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>, id: PatternID) -&gt; Pattern&lt;<span class="lifetime">'_</span>&gt; {
<a href=#143 id=143 data-nosnippet>143</a> Pattern(<span class="kw-2">&amp;</span><span class="self">self</span>.by_id[id])
<a href=#144 id=144 data-nosnippet>144</a> }
<a href=#145 id=145 data-nosnippet>145</a>
<a href=#146 id=146 data-nosnippet>146</a> <span class="doccomment">/// Return the pattern with the given identifier without performing bounds
<a href=#147 id=147 data-nosnippet>147</a> /// checks.
<a href=#148 id=148 data-nosnippet>148</a> ///
<a href=#149 id=149 data-nosnippet>149</a> /// # Safety
<a href=#150 id=150 data-nosnippet>150</a> ///
<a href=#151 id=151 data-nosnippet>151</a> /// Callers must ensure that a pattern with the given identifier exists
<a href=#152 id=152 data-nosnippet>152</a> /// before using this method.
<a href=#153 id=153 data-nosnippet>153</a> </span><span class="kw">pub</span>(<span class="kw">crate</span>) <span class="kw">unsafe fn </span>get_unchecked(<span class="kw-2">&amp;</span><span class="self">self</span>, id: PatternID) -&gt; Pattern&lt;<span class="lifetime">'_</span>&gt; {
<a href=#154 id=154 data-nosnippet>154</a> Pattern(<span class="self">self</span>.by_id.get_unchecked(id.as_usize()))
<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">/// Return an iterator over all the patterns in this collection, in the
<a href=#158 id=158 data-nosnippet>158</a> /// order in which they should be matched.
<a href=#159 id=159 data-nosnippet>159</a> ///
<a href=#160 id=160 data-nosnippet>160</a> /// Specifically, in a naive multi-pattern matcher, the following is
<a href=#161 id=161 data-nosnippet>161</a> /// guaranteed to satisfy the match semantics of this collection of
<a href=#162 id=162 data-nosnippet>162</a> /// patterns:
<a href=#163 id=163 data-nosnippet>163</a> ///
<a href=#164 id=164 data-nosnippet>164</a> /// ```ignore
<a href=#165 id=165 data-nosnippet>165</a> /// for i in 0..haystack.len():
<a href=#166 id=166 data-nosnippet>166</a> /// for p in patterns.iter():
<a href=#167 id=167 data-nosnippet>167</a> /// if haystack[i..].starts_with(p.bytes()):
<a href=#168 id=168 data-nosnippet>168</a> /// return Match(p.id(), i, i + p.bytes().len())
<a href=#169 id=169 data-nosnippet>169</a> /// ```
<a href=#170 id=170 data-nosnippet>170</a> ///
<a href=#171 id=171 data-nosnippet>171</a> /// Namely, among the patterns in a collection, if they are matched in
<a href=#172 id=172 data-nosnippet>172</a> /// the order provided by this iterator, then the result is guaranteed
<a href=#173 id=173 data-nosnippet>173</a> /// to satisfy the correct match semantics. (Either leftmost-first or
<a href=#174 id=174 data-nosnippet>174</a> /// leftmost-longest.)
<a href=#175 id=175 data-nosnippet>175</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; PatternIter&lt;<span class="lifetime">'_</span>&gt; {
<a href=#176 id=176 data-nosnippet>176</a> PatternIter { patterns: <span class="self">self</span>, i: <span class="number">0 </span>}
<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>
<a href=#180 id=180 data-nosnippet>180</a><span class="doccomment">/// An iterator over the patterns in the `Patterns` collection.
<a href=#181 id=181 data-nosnippet>181</a>///
<a href=#182 id=182 data-nosnippet>182</a>/// The order of the patterns provided by this iterator is consistent with the
<a href=#183 id=183 data-nosnippet>183</a>/// match semantics of the originating collection of patterns.
<a href=#184 id=184 data-nosnippet>184</a>///
<a href=#185 id=185 data-nosnippet>185</a>/// The lifetime `'p` corresponds to the lifetime of the collection of patterns
<a href=#186 id=186 data-nosnippet>186</a>/// this is iterating over.
<a href=#187 id=187 data-nosnippet>187</a></span><span class="attr">#[derive(Debug)]
<a href=#188 id=188 data-nosnippet>188</a></span><span class="kw">pub</span>(<span class="kw">crate</span>) <span class="kw">struct </span>PatternIter&lt;<span class="lifetime">'p</span>&gt; {
<a href=#189 id=189 data-nosnippet>189</a> patterns: <span class="kw-2">&amp;</span><span class="lifetime">'p </span>Patterns,
<a href=#190 id=190 data-nosnippet>190</a> i: usize,
<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><span class="kw">impl</span>&lt;<span class="lifetime">'p</span>&gt; Iterator <span class="kw">for </span>PatternIter&lt;<span class="lifetime">'p</span>&gt; {
<a href=#194 id=194 data-nosnippet>194</a> <span class="kw">type </span>Item = (PatternID, Pattern&lt;<span class="lifetime">'p</span>&gt;);
<a href=#195 id=195 data-nosnippet>195</a>
<a href=#196 id=196 data-nosnippet>196</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;(PatternID, Pattern&lt;<span class="lifetime">'p</span>&gt;)&gt; {
<a href=#197 id=197 data-nosnippet>197</a> <span class="kw">if </span><span class="self">self</span>.i &gt;= <span class="self">self</span>.patterns.len() {
<a href=#198 id=198 data-nosnippet>198</a> <span class="kw">return </span><span class="prelude-val">None</span>;
<a href=#199 id=199 data-nosnippet>199</a> }
<a href=#200 id=200 data-nosnippet>200</a> <span class="kw">let </span>id = <span class="self">self</span>.patterns.order[<span class="self">self</span>.i];
<a href=#201 id=201 data-nosnippet>201</a> <span class="kw">let </span>p = <span class="self">self</span>.patterns.get(id);
<a href=#202 id=202 data-nosnippet>202</a> <span class="self">self</span>.i += <span class="number">1</span>;
<a href=#203 id=203 data-nosnippet>203</a> <span class="prelude-val">Some</span>((id, p))
<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>
<a href=#207 id=207 data-nosnippet>207</a><span class="doccomment">/// A pattern that is used in packed searching.
<a href=#208 id=208 data-nosnippet>208</a></span><span class="attr">#[derive(Clone)]
<a href=#209 id=209 data-nosnippet>209</a></span><span class="kw">pub</span>(<span class="kw">crate</span>) <span class="kw">struct </span>Pattern&lt;<span class="lifetime">'a</span>&gt;(<span class="kw-2">&amp;</span><span class="lifetime">'a </span>[u8]);
<a href=#210 id=210 data-nosnippet>210</a>
<a href=#211 id=211 data-nosnippet>211</a><span class="kw">impl</span>&lt;<span class="lifetime">'a</span>&gt; fmt::Debug <span class="kw">for </span>Pattern&lt;<span class="lifetime">'a</span>&gt; {
<a href=#212 id=212 data-nosnippet>212</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>fmt::Formatter&lt;<span class="lifetime">'_</span>&gt;) -&gt; fmt::Result {
<a href=#213 id=213 data-nosnippet>213</a> f.debug_struct(<span class="string">"Pattern"</span>)
<a href=#214 id=214 data-nosnippet>214</a> .field(<span class="string">"lit"</span>, <span class="kw-2">&amp;</span>String::from_utf8_lossy(<span class="self">self</span>.<span class="number">0</span>))
<a href=#215 id=215 data-nosnippet>215</a> .finish()
<a href=#216 id=216 data-nosnippet>216</a> }
<a href=#217 id=217 data-nosnippet>217</a>}
<a href=#218 id=218 data-nosnippet>218</a>
<a href=#219 id=219 data-nosnippet>219</a><span class="kw">impl</span>&lt;<span class="lifetime">'p</span>&gt; Pattern&lt;<span class="lifetime">'p</span>&gt; {
<a href=#220 id=220 data-nosnippet>220</a> <span class="doccomment">/// Returns the length of this pattern, in bytes.
<a href=#221 id=221 data-nosnippet>221</a> </span><span class="kw">pub</span>(<span class="kw">crate</span>) <span class="kw">fn </span>len(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; usize {
<a href=#222 id=222 data-nosnippet>222</a> <span class="self">self</span>.<span class="number">0</span>.len()
<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="doccomment">/// Returns the bytes of this pattern.
<a href=#226 id=226 data-nosnippet>226</a> </span><span class="kw">pub</span>(<span class="kw">crate</span>) <span class="kw">fn </span>bytes(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; <span class="kw-2">&amp;</span>[u8] {
<a href=#227 id=227 data-nosnippet>227</a> <span class="self">self</span>.<span class="number">0
<a href=#228 id=228 data-nosnippet>228</a> </span>}
<a href=#229 id=229 data-nosnippet>229</a>
<a href=#230 id=230 data-nosnippet>230</a> <span class="doccomment">/// Returns the first `len` low nybbles from this pattern. If this pattern
<a href=#231 id=231 data-nosnippet>231</a> /// is shorter than `len`, then this panics.
<a href=#232 id=232 data-nosnippet>232</a> </span><span class="kw">pub</span>(<span class="kw">crate</span>) <span class="kw">fn </span>low_nybbles(<span class="kw-2">&amp;</span><span class="self">self</span>, len: usize) -&gt; Box&lt;[u8]&gt; {
<a href=#233 id=233 data-nosnippet>233</a> <span class="kw">let </span><span class="kw-2">mut </span>nybs = <span class="macro">vec!</span>[<span class="number">0</span>; len].into_boxed_slice();
<a href=#234 id=234 data-nosnippet>234</a> <span class="kw">for </span>(i, byte) <span class="kw">in </span><span class="self">self</span>.bytes().iter().take(len).enumerate() {
<a href=#235 id=235 data-nosnippet>235</a> nybs[i] = byte &amp; <span class="number">0xF</span>;
<a href=#236 id=236 data-nosnippet>236</a> }
<a href=#237 id=237 data-nosnippet>237</a> nybs
<a href=#238 id=238 data-nosnippet>238</a> }
<a href=#239 id=239 data-nosnippet>239</a>
<a href=#240 id=240 data-nosnippet>240</a> <span class="doccomment">/// Returns true if this pattern is a prefix of the given bytes.
<a href=#241 id=241 data-nosnippet>241</a> </span><span class="attr">#[inline(always)]
<a href=#242 id=242 data-nosnippet>242</a> </span><span class="kw">pub</span>(<span class="kw">crate</span>) <span class="kw">fn </span>is_prefix(<span class="kw-2">&amp;</span><span class="self">self</span>, bytes: <span class="kw-2">&amp;</span>[u8]) -&gt; bool {
<a href=#243 id=243 data-nosnippet>243</a> is_prefix(bytes, <span class="self">self</span>.bytes())
<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> <span class="doccomment">/// Returns true if this pattern is a prefix of the haystack given by the
<a href=#247 id=247 data-nosnippet>247</a> /// raw `start` and `end` pointers.
<a href=#248 id=248 data-nosnippet>248</a> ///
<a href=#249 id=249 data-nosnippet>249</a> /// # Safety
<a href=#250 id=250 data-nosnippet>250</a> ///
<a href=#251 id=251 data-nosnippet>251</a> /// * It must be the case that `start &lt; end` and that the distance between
<a href=#252 id=252 data-nosnippet>252</a> /// them is at least equal to `V::BYTES`. That is, it must always be valid
<a href=#253 id=253 data-nosnippet>253</a> /// to do at least an unaligned load of `V` at `start`.
<a href=#254 id=254 data-nosnippet>254</a> /// * Both `start` and `end` must be valid for reads.
<a href=#255 id=255 data-nosnippet>255</a> /// * Both `start` and `end` must point to an initialized value.
<a href=#256 id=256 data-nosnippet>256</a> /// * Both `start` and `end` must point to the same allocated object and
<a href=#257 id=257 data-nosnippet>257</a> /// must either be in bounds or at most one byte past the end of the
<a href=#258 id=258 data-nosnippet>258</a> /// allocated object.
<a href=#259 id=259 data-nosnippet>259</a> /// * Both `start` and `end` must be _derived from_ a pointer to the same
<a href=#260 id=260 data-nosnippet>260</a> /// object.
<a href=#261 id=261 data-nosnippet>261</a> /// * The distance between `start` and `end` must not overflow `isize`.
<a href=#262 id=262 data-nosnippet>262</a> /// * The distance being in bounds must not rely on "wrapping around" the
<a href=#263 id=263 data-nosnippet>263</a> /// address space.
<a href=#264 id=264 data-nosnippet>264</a> </span><span class="attr">#[inline(always)]
<a href=#265 id=265 data-nosnippet>265</a> </span><span class="kw">pub</span>(<span class="kw">crate</span>) <span class="kw">unsafe fn </span>is_prefix_raw(
<a href=#266 id=266 data-nosnippet>266</a> <span class="kw-2">&amp;</span><span class="self">self</span>,
<a href=#267 id=267 data-nosnippet>267</a> start: <span class="kw-2">*const </span>u8,
<a href=#268 id=268 data-nosnippet>268</a> end: <span class="kw-2">*const </span>u8,
<a href=#269 id=269 data-nosnippet>269</a> ) -&gt; bool {
<a href=#270 id=270 data-nosnippet>270</a> <span class="kw">let </span>patlen = <span class="self">self</span>.bytes().len();
<a href=#271 id=271 data-nosnippet>271</a> <span class="kw">let </span>haylen = end.distance(start);
<a href=#272 id=272 data-nosnippet>272</a> <span class="kw">if </span>patlen &gt; haylen {
<a href=#273 id=273 data-nosnippet>273</a> <span class="kw">return </span><span class="bool-val">false</span>;
<a href=#274 id=274 data-nosnippet>274</a> }
<a href=#275 id=275 data-nosnippet>275</a> <span class="comment">// SAFETY: We've checked that the haystack has length at least equal
<a href=#276 id=276 data-nosnippet>276</a> // to this pattern. All other safety concerns are the responsibility
<a href=#277 id=277 data-nosnippet>277</a> // of the caller.
<a href=#278 id=278 data-nosnippet>278</a> </span>is_equal_raw(start, <span class="self">self</span>.bytes().as_ptr(), patlen)
<a href=#279 id=279 data-nosnippet>279</a> }
<a href=#280 id=280 data-nosnippet>280</a>}
<a href=#281 id=281 data-nosnippet>281</a>
<a href=#282 id=282 data-nosnippet>282</a><span class="doccomment">/// Returns true if and only if `needle` is a prefix of `haystack`.
<a href=#283 id=283 data-nosnippet>283</a>///
<a href=#284 id=284 data-nosnippet>284</a>/// This uses a latency optimized variant of `memcmp` internally which *might*
<a href=#285 id=285 data-nosnippet>285</a>/// make this faster for very short strings.
<a href=#286 id=286 data-nosnippet>286</a>///
<a href=#287 id=287 data-nosnippet>287</a>/// # Inlining
<a href=#288 id=288 data-nosnippet>288</a>///
<a href=#289 id=289 data-nosnippet>289</a>/// This routine is marked `inline(always)`. If you want to call this function
<a href=#290 id=290 data-nosnippet>290</a>/// in a way that is not always inlined, you'll need to wrap a call to it in
<a href=#291 id=291 data-nosnippet>291</a>/// another function that is marked as `inline(never)` or just `inline`.
<a href=#292 id=292 data-nosnippet>292</a></span><span class="attr">#[inline(always)]
<a href=#293 id=293 data-nosnippet>293</a></span><span class="kw">fn </span>is_prefix(haystack: <span class="kw-2">&amp;</span>[u8], needle: <span class="kw-2">&amp;</span>[u8]) -&gt; bool {
<a href=#294 id=294 data-nosnippet>294</a> <span class="kw">if </span>needle.len() &gt; haystack.len() {
<a href=#295 id=295 data-nosnippet>295</a> <span class="kw">return </span><span class="bool-val">false</span>;
<a href=#296 id=296 data-nosnippet>296</a> }
<a href=#297 id=297 data-nosnippet>297</a> <span class="comment">// SAFETY: Our pointers are derived directly from borrowed slices which
<a href=#298 id=298 data-nosnippet>298</a> // uphold all of our safety guarantees except for length. We account for
<a href=#299 id=299 data-nosnippet>299</a> // length with the check above.
<a href=#300 id=300 data-nosnippet>300</a> </span><span class="kw">unsafe </span>{ is_equal_raw(haystack.as_ptr(), needle.as_ptr(), needle.len()) }
<a href=#301 id=301 data-nosnippet>301</a>}
<a href=#302 id=302 data-nosnippet>302</a>
<a href=#303 id=303 data-nosnippet>303</a><span class="doccomment">/// Compare corresponding bytes in `x` and `y` for equality.
<a href=#304 id=304 data-nosnippet>304</a>///
<a href=#305 id=305 data-nosnippet>305</a>/// That is, this returns true if and only if `x.len() == y.len()` and
<a href=#306 id=306 data-nosnippet>306</a>/// `x[i] == y[i]` for all `0 &lt;= i &lt; x.len()`.
<a href=#307 id=307 data-nosnippet>307</a>///
<a href=#308 id=308 data-nosnippet>308</a>/// Note that this isn't used. We only use it in tests as a convenient way
<a href=#309 id=309 data-nosnippet>309</a>/// of testing `is_equal_raw`.
<a href=#310 id=310 data-nosnippet>310</a>///
<a href=#311 id=311 data-nosnippet>311</a>/// # Inlining
<a href=#312 id=312 data-nosnippet>312</a>///
<a href=#313 id=313 data-nosnippet>313</a>/// This routine is marked `inline(always)`. If you want to call this function
<a href=#314 id=314 data-nosnippet>314</a>/// in a way that is not always inlined, you'll need to wrap a call to it in
<a href=#315 id=315 data-nosnippet>315</a>/// another function that is marked as `inline(never)` or just `inline`.
<a href=#316 id=316 data-nosnippet>316</a>///
<a href=#317 id=317 data-nosnippet>317</a>/// # Motivation
<a href=#318 id=318 data-nosnippet>318</a>///
<a href=#319 id=319 data-nosnippet>319</a>/// Why not use slice equality instead? Well, slice equality usually results in
<a href=#320 id=320 data-nosnippet>320</a>/// a call out to the current platform's `libc` which might not be inlineable
<a href=#321 id=321 data-nosnippet>321</a>/// or have other overhead. This routine isn't guaranteed to be a win, but it
<a href=#322 id=322 data-nosnippet>322</a>/// might be in some cases.
<a href=#323 id=323 data-nosnippet>323</a></span><span class="attr">#[cfg(test)]
<a href=#324 id=324 data-nosnippet>324</a>#[inline(always)]
<a href=#325 id=325 data-nosnippet>325</a></span><span class="kw">fn </span>is_equal(x: <span class="kw-2">&amp;</span>[u8], y: <span class="kw-2">&amp;</span>[u8]) -&gt; bool {
<a href=#326 id=326 data-nosnippet>326</a> <span class="kw">if </span>x.len() != y.len() {
<a href=#327 id=327 data-nosnippet>327</a> <span class="kw">return </span><span class="bool-val">false</span>;
<a href=#328 id=328 data-nosnippet>328</a> }
<a href=#329 id=329 data-nosnippet>329</a> <span class="comment">// SAFETY: Our pointers are derived directly from borrowed slices which
<a href=#330 id=330 data-nosnippet>330</a> // uphold all of our safety guarantees except for length. We account for
<a href=#331 id=331 data-nosnippet>331</a> // length with the check above.
<a href=#332 id=332 data-nosnippet>332</a> </span><span class="kw">unsafe </span>{ is_equal_raw(x.as_ptr(), y.as_ptr(), x.len()) }
<a href=#333 id=333 data-nosnippet>333</a>}
<a href=#334 id=334 data-nosnippet>334</a>
<a href=#335 id=335 data-nosnippet>335</a><span class="doccomment">/// Compare `n` bytes at the given pointers for equality.
<a href=#336 id=336 data-nosnippet>336</a>///
<a href=#337 id=337 data-nosnippet>337</a>/// This returns true if and only if `*x.add(i) == *y.add(i)` for all
<a href=#338 id=338 data-nosnippet>338</a>/// `0 &lt;= i &lt; n`.
<a href=#339 id=339 data-nosnippet>339</a>///
<a href=#340 id=340 data-nosnippet>340</a>/// # Inlining
<a href=#341 id=341 data-nosnippet>341</a>///
<a href=#342 id=342 data-nosnippet>342</a>/// This routine is marked `inline(always)`. If you want to call this function
<a href=#343 id=343 data-nosnippet>343</a>/// in a way that is not always inlined, you'll need to wrap a call to it in
<a href=#344 id=344 data-nosnippet>344</a>/// another function that is marked as `inline(never)` or just `inline`.
<a href=#345 id=345 data-nosnippet>345</a>///
<a href=#346 id=346 data-nosnippet>346</a>/// # Motivation
<a href=#347 id=347 data-nosnippet>347</a>///
<a href=#348 id=348 data-nosnippet>348</a>/// Why not use slice equality instead? Well, slice equality usually results in
<a href=#349 id=349 data-nosnippet>349</a>/// a call out to the current platform's `libc` which might not be inlineable
<a href=#350 id=350 data-nosnippet>350</a>/// or have other overhead. This routine isn't guaranteed to be a win, but it
<a href=#351 id=351 data-nosnippet>351</a>/// might be in some cases.
<a href=#352 id=352 data-nosnippet>352</a>///
<a href=#353 id=353 data-nosnippet>353</a>/// # Safety
<a href=#354 id=354 data-nosnippet>354</a>///
<a href=#355 id=355 data-nosnippet>355</a>/// * Both `x` and `y` must be valid for reads of up to `n` bytes.
<a href=#356 id=356 data-nosnippet>356</a>/// * Both `x` and `y` must point to an initialized value.
<a href=#357 id=357 data-nosnippet>357</a>/// * Both `x` and `y` must each point to an allocated object and
<a href=#358 id=358 data-nosnippet>358</a>/// must either be in bounds or at most one byte past the end of the
<a href=#359 id=359 data-nosnippet>359</a>/// allocated object. `x` and `y` do not need to point to the same allocated
<a href=#360 id=360 data-nosnippet>360</a>/// object, but they may.
<a href=#361 id=361 data-nosnippet>361</a>/// * Both `x` and `y` must be _derived from_ a pointer to their respective
<a href=#362 id=362 data-nosnippet>362</a>/// allocated objects.
<a href=#363 id=363 data-nosnippet>363</a>/// * The distance between `x` and `x+n` must not overflow `isize`. Similarly
<a href=#364 id=364 data-nosnippet>364</a>/// for `y` and `y+n`.
<a href=#365 id=365 data-nosnippet>365</a>/// * The distance being in bounds must not rely on "wrapping around" the
<a href=#366 id=366 data-nosnippet>366</a>/// address space.
<a href=#367 id=367 data-nosnippet>367</a></span><span class="attr">#[inline(always)]
<a href=#368 id=368 data-nosnippet>368</a></span><span class="kw">unsafe fn </span>is_equal_raw(<span class="kw-2">mut </span>x: <span class="kw-2">*const </span>u8, <span class="kw-2">mut </span>y: <span class="kw-2">*const </span>u8, n: usize) -&gt; bool {
<a href=#369 id=369 data-nosnippet>369</a> <span class="comment">// If we don't have enough bytes to do 4-byte at a time loads, then
<a href=#370 id=370 data-nosnippet>370</a> // handle each possible length specially. Note that I used to have a
<a href=#371 id=371 data-nosnippet>371</a> // byte-at-a-time loop here and that turned out to be quite a bit slower
<a href=#372 id=372 data-nosnippet>372</a> // for the memmem/pathological/defeat-simple-vector-alphabet benchmark.
<a href=#373 id=373 data-nosnippet>373</a> </span><span class="kw">if </span>n &lt; <span class="number">4 </span>{
<a href=#374 id=374 data-nosnippet>374</a> <span class="kw">return match </span>n {
<a href=#375 id=375 data-nosnippet>375</a> <span class="number">0 </span>=&gt; <span class="bool-val">true</span>,
<a href=#376 id=376 data-nosnippet>376</a> <span class="number">1 </span>=&gt; x.read() == y.read(),
<a href=#377 id=377 data-nosnippet>377</a> <span class="number">2 </span>=&gt; {
<a href=#378 id=378 data-nosnippet>378</a> x.cast::&lt;u16&gt;().read_unaligned()
<a href=#379 id=379 data-nosnippet>379</a> == y.cast::&lt;u16&gt;().read_unaligned()
<a href=#380 id=380 data-nosnippet>380</a> }
<a href=#381 id=381 data-nosnippet>381</a> <span class="comment">// I also tried copy_nonoverlapping here and it looks like the
<a href=#382 id=382 data-nosnippet>382</a> // codegen is the same.
<a href=#383 id=383 data-nosnippet>383</a> </span><span class="number">3 </span>=&gt; x.cast::&lt;[u8; <span class="number">3</span>]&gt;().read() == y.cast::&lt;[u8; <span class="number">3</span>]&gt;().read(),
<a href=#384 id=384 data-nosnippet>384</a> <span class="kw">_ </span>=&gt; <span class="macro">unreachable!</span>(),
<a href=#385 id=385 data-nosnippet>385</a> };
<a href=#386 id=386 data-nosnippet>386</a> }
<a href=#387 id=387 data-nosnippet>387</a> <span class="comment">// When we have 4 or more bytes to compare, then proceed in chunks of 4 at
<a href=#388 id=388 data-nosnippet>388</a> // a time using unaligned loads.
<a href=#389 id=389 data-nosnippet>389</a> //
<a href=#390 id=390 data-nosnippet>390</a> // Also, why do 4 byte loads instead of, say, 8 byte loads? The reason is
<a href=#391 id=391 data-nosnippet>391</a> // that this particular version of memcmp is likely to be called with tiny
<a href=#392 id=392 data-nosnippet>392</a> // needles. That means that if we do 8 byte loads, then a higher proportion
<a href=#393 id=393 data-nosnippet>393</a> // of memcmp calls will use the slower variant above. With that said, this
<a href=#394 id=394 data-nosnippet>394</a> // is a hypothesis and is only loosely supported by benchmarks. There's
<a href=#395 id=395 data-nosnippet>395</a> // likely some improvement that could be made here. The main thing here
<a href=#396 id=396 data-nosnippet>396</a> // though is to optimize for latency, not throughput.
<a href=#397 id=397 data-nosnippet>397</a>
<a href=#398 id=398 data-nosnippet>398</a> // SAFETY: The caller is responsible for ensuring the pointers we get are
<a href=#399 id=399 data-nosnippet>399</a> // valid and readable for at least `n` bytes. We also do unaligned loads,
<a href=#400 id=400 data-nosnippet>400</a> // so there's no need to ensure we're aligned. (This is justified by this
<a href=#401 id=401 data-nosnippet>401</a> // routine being specifically for short strings.)
<a href=#402 id=402 data-nosnippet>402</a> </span><span class="kw">let </span>xend = x.add(n.wrapping_sub(<span class="number">4</span>));
<a href=#403 id=403 data-nosnippet>403</a> <span class="kw">let </span>yend = y.add(n.wrapping_sub(<span class="number">4</span>));
<a href=#404 id=404 data-nosnippet>404</a> <span class="kw">while </span>x &lt; xend {
<a href=#405 id=405 data-nosnippet>405</a> <span class="kw">let </span>vx = x.cast::&lt;u32&gt;().read_unaligned();
<a href=#406 id=406 data-nosnippet>406</a> <span class="kw">let </span>vy = y.cast::&lt;u32&gt;().read_unaligned();
<a href=#407 id=407 data-nosnippet>407</a> <span class="kw">if </span><span class="macro">vx !</span>= vy {
<a href=#408 id=408 data-nosnippet>408</a> <span class="kw">return </span><span class="bool-val">false</span>;
<a href=#409 id=409 data-nosnippet>409</a> }
<a href=#410 id=410 data-nosnippet>410</a> x = x.add(<span class="number">4</span>);
<a href=#411 id=411 data-nosnippet>411</a> y = y.add(<span class="number">4</span>);
<a href=#412 id=412 data-nosnippet>412</a> }
<a href=#413 id=413 data-nosnippet>413</a> <span class="kw">let </span>vx = xend.cast::&lt;u32&gt;().read_unaligned();
<a href=#414 id=414 data-nosnippet>414</a> <span class="kw">let </span>vy = yend.cast::&lt;u32&gt;().read_unaligned();
<a href=#415 id=415 data-nosnippet>415</a> vx == vy
<a href=#416 id=416 data-nosnippet>416</a>}
<a href=#417 id=417 data-nosnippet>417</a>
<a href=#418 id=418 data-nosnippet>418</a><span class="attr">#[cfg(test)]
<a href=#419 id=419 data-nosnippet>419</a></span><span class="kw">mod </span>tests {
<a href=#420 id=420 data-nosnippet>420</a> <span class="kw">use super</span>::<span class="kw-2">*</span>;
<a href=#421 id=421 data-nosnippet>421</a>
<a href=#422 id=422 data-nosnippet>422</a> <span class="attr">#[test]
<a href=#423 id=423 data-nosnippet>423</a> </span><span class="kw">fn </span>equals_different_lengths() {
<a href=#424 id=424 data-nosnippet>424</a> <span class="macro">assert!</span>(!is_equal(<span class="string">b""</span>, <span class="string">b"a"</span>));
<a href=#425 id=425 data-nosnippet>425</a> <span class="macro">assert!</span>(!is_equal(<span class="string">b"a"</span>, <span class="string">b""</span>));
<a href=#426 id=426 data-nosnippet>426</a> <span class="macro">assert!</span>(!is_equal(<span class="string">b"ab"</span>, <span class="string">b"a"</span>));
<a href=#427 id=427 data-nosnippet>427</a> <span class="macro">assert!</span>(!is_equal(<span class="string">b"a"</span>, <span class="string">b"ab"</span>));
<a href=#428 id=428 data-nosnippet>428</a> }
<a href=#429 id=429 data-nosnippet>429</a>
<a href=#430 id=430 data-nosnippet>430</a> <span class="attr">#[test]
<a href=#431 id=431 data-nosnippet>431</a> </span><span class="kw">fn </span>equals_mismatch() {
<a href=#432 id=432 data-nosnippet>432</a> <span class="kw">let </span>one_mismatch = [
<a href=#433 id=433 data-nosnippet>433</a> (<span class="kw-2">&amp;</span><span class="string">b"a"</span>[..], <span class="kw-2">&amp;</span><span class="string">b"x"</span>[..]),
<a href=#434 id=434 data-nosnippet>434</a> (<span class="kw-2">&amp;</span><span class="string">b"ab"</span>[..], <span class="kw-2">&amp;</span><span class="string">b"ax"</span>[..]),
<a href=#435 id=435 data-nosnippet>435</a> (<span class="kw-2">&amp;</span><span class="string">b"abc"</span>[..], <span class="kw-2">&amp;</span><span class="string">b"abx"</span>[..]),
<a href=#436 id=436 data-nosnippet>436</a> (<span class="kw-2">&amp;</span><span class="string">b"abcd"</span>[..], <span class="kw-2">&amp;</span><span class="string">b"abcx"</span>[..]),
<a href=#437 id=437 data-nosnippet>437</a> (<span class="kw-2">&amp;</span><span class="string">b"abcde"</span>[..], <span class="kw-2">&amp;</span><span class="string">b"abcdx"</span>[..]),
<a href=#438 id=438 data-nosnippet>438</a> (<span class="kw-2">&amp;</span><span class="string">b"abcdef"</span>[..], <span class="kw-2">&amp;</span><span class="string">b"abcdex"</span>[..]),
<a href=#439 id=439 data-nosnippet>439</a> (<span class="kw-2">&amp;</span><span class="string">b"abcdefg"</span>[..], <span class="kw-2">&amp;</span><span class="string">b"abcdefx"</span>[..]),
<a href=#440 id=440 data-nosnippet>440</a> (<span class="kw-2">&amp;</span><span class="string">b"abcdefgh"</span>[..], <span class="kw-2">&amp;</span><span class="string">b"abcdefgx"</span>[..]),
<a href=#441 id=441 data-nosnippet>441</a> (<span class="kw-2">&amp;</span><span class="string">b"abcdefghi"</span>[..], <span class="kw-2">&amp;</span><span class="string">b"abcdefghx"</span>[..]),
<a href=#442 id=442 data-nosnippet>442</a> (<span class="kw-2">&amp;</span><span class="string">b"abcdefghij"</span>[..], <span class="kw-2">&amp;</span><span class="string">b"abcdefghix"</span>[..]),
<a href=#443 id=443 data-nosnippet>443</a> (<span class="kw-2">&amp;</span><span class="string">b"abcdefghijk"</span>[..], <span class="kw-2">&amp;</span><span class="string">b"abcdefghijx"</span>[..]),
<a href=#444 id=444 data-nosnippet>444</a> (<span class="kw-2">&amp;</span><span class="string">b"abcdefghijkl"</span>[..], <span class="kw-2">&amp;</span><span class="string">b"abcdefghijkx"</span>[..]),
<a href=#445 id=445 data-nosnippet>445</a> (<span class="kw-2">&amp;</span><span class="string">b"abcdefghijklm"</span>[..], <span class="kw-2">&amp;</span><span class="string">b"abcdefghijklx"</span>[..]),
<a href=#446 id=446 data-nosnippet>446</a> (<span class="kw-2">&amp;</span><span class="string">b"abcdefghijklmn"</span>[..], <span class="kw-2">&amp;</span><span class="string">b"abcdefghijklmx"</span>[..]),
<a href=#447 id=447 data-nosnippet>447</a> ];
<a href=#448 id=448 data-nosnippet>448</a> <span class="kw">for </span>(x, y) <span class="kw">in </span>one_mismatch {
<a href=#449 id=449 data-nosnippet>449</a> <span class="macro">assert_eq!</span>(x.len(), y.len(), <span class="string">"lengths should match"</span>);
<a href=#450 id=450 data-nosnippet>450</a> <span class="macro">assert!</span>(!is_equal(x, y));
<a href=#451 id=451 data-nosnippet>451</a> <span class="macro">assert!</span>(!is_equal(y, x));
<a href=#452 id=452 data-nosnippet>452</a> }
<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="attr">#[test]
<a href=#456 id=456 data-nosnippet>456</a> </span><span class="kw">fn </span>equals_yes() {
<a href=#457 id=457 data-nosnippet>457</a> <span class="macro">assert!</span>(is_equal(<span class="string">b""</span>, <span class="string">b""</span>));
<a href=#458 id=458 data-nosnippet>458</a> <span class="macro">assert!</span>(is_equal(<span class="string">b"a"</span>, <span class="string">b"a"</span>));
<a href=#459 id=459 data-nosnippet>459</a> <span class="macro">assert!</span>(is_equal(<span class="string">b"ab"</span>, <span class="string">b"ab"</span>));
<a href=#460 id=460 data-nosnippet>460</a> <span class="macro">assert!</span>(is_equal(<span class="string">b"abc"</span>, <span class="string">b"abc"</span>));
<a href=#461 id=461 data-nosnippet>461</a> <span class="macro">assert!</span>(is_equal(<span class="string">b"abcd"</span>, <span class="string">b"abcd"</span>));
<a href=#462 id=462 data-nosnippet>462</a> <span class="macro">assert!</span>(is_equal(<span class="string">b"abcde"</span>, <span class="string">b"abcde"</span>));
<a href=#463 id=463 data-nosnippet>463</a> <span class="macro">assert!</span>(is_equal(<span class="string">b"abcdef"</span>, <span class="string">b"abcdef"</span>));
<a href=#464 id=464 data-nosnippet>464</a> <span class="macro">assert!</span>(is_equal(<span class="string">b"abcdefg"</span>, <span class="string">b"abcdefg"</span>));
<a href=#465 id=465 data-nosnippet>465</a> <span class="macro">assert!</span>(is_equal(<span class="string">b"abcdefgh"</span>, <span class="string">b"abcdefgh"</span>));
<a href=#466 id=466 data-nosnippet>466</a> <span class="macro">assert!</span>(is_equal(<span class="string">b"abcdefghi"</span>, <span class="string">b"abcdefghi"</span>));
<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="attr">#[test]
<a href=#470 id=470 data-nosnippet>470</a> </span><span class="kw">fn </span>prefix() {
<a href=#471 id=471 data-nosnippet>471</a> <span class="macro">assert!</span>(is_prefix(<span class="string">b""</span>, <span class="string">b""</span>));
<a href=#472 id=472 data-nosnippet>472</a> <span class="macro">assert!</span>(is_prefix(<span class="string">b"a"</span>, <span class="string">b""</span>));
<a href=#473 id=473 data-nosnippet>473</a> <span class="macro">assert!</span>(is_prefix(<span class="string">b"ab"</span>, <span class="string">b""</span>));
<a href=#474 id=474 data-nosnippet>474</a> <span class="macro">assert!</span>(is_prefix(<span class="string">b"foo"</span>, <span class="string">b"foo"</span>));
<a href=#475 id=475 data-nosnippet>475</a> <span class="macro">assert!</span>(is_prefix(<span class="string">b"foobar"</span>, <span class="string">b"foo"</span>));
<a href=#476 id=476 data-nosnippet>476</a>
<a href=#477 id=477 data-nosnippet>477</a> <span class="macro">assert!</span>(!is_prefix(<span class="string">b"foo"</span>, <span class="string">b"fob"</span>));
<a href=#478 id=478 data-nosnippet>478</a> <span class="macro">assert!</span>(!is_prefix(<span class="string">b"foobar"</span>, <span class="string">b"fob"</span>));
<a href=#479 id=479 data-nosnippet>479</a> }
<a href=#480 id=480 data-nosnippet>480</a>}
</code></pre></div></section></main></body></html>

View File

@@ -0,0 +1,169 @@
<!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/packed/rabinkarp.rs`."><title>rabinkarp.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/packed/</div>rabinkarp.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::{sync::Arc, vec, 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>::{packed::pattern::Patterns, util::search::Match, PatternID};
<a href=#4 id=4 data-nosnippet>4</a>
<a href=#5 id=5 data-nosnippet>5</a><span class="doccomment">/// The type of the rolling hash used in the Rabin-Karp algorithm.
<a href=#6 id=6 data-nosnippet>6</a></span><span class="kw">type </span>Hash = usize;
<a href=#7 id=7 data-nosnippet>7</a>
<a href=#8 id=8 data-nosnippet>8</a><span class="doccomment">/// The number of buckets to store our patterns in. We don't want this to be
<a href=#9 id=9 data-nosnippet>9</a>/// too big in order to avoid wasting memory, but we don't want it to be too
<a href=#10 id=10 data-nosnippet>10</a>/// small either to avoid spending too much time confirming literals.
<a href=#11 id=11 data-nosnippet>11</a>///
<a href=#12 id=12 data-nosnippet>12</a>/// The number of buckets MUST be a power of two. Otherwise, determining the
<a href=#13 id=13 data-nosnippet>13</a>/// bucket from a hash will slow down the code considerably. Using a power
<a href=#14 id=14 data-nosnippet>14</a>/// of two means `hash % NUM_BUCKETS` can compile down to a simple `and`
<a href=#15 id=15 data-nosnippet>15</a>/// instruction.
<a href=#16 id=16 data-nosnippet>16</a></span><span class="kw">const </span>NUM_BUCKETS: usize = <span class="number">64</span>;
<a href=#17 id=17 data-nosnippet>17</a>
<a href=#18 id=18 data-nosnippet>18</a><span class="doccomment">/// An implementation of the Rabin-Karp algorithm. The main idea of this
<a href=#19 id=19 data-nosnippet>19</a>/// algorithm is to maintain a rolling hash as it moves through the input, and
<a href=#20 id=20 data-nosnippet>20</a>/// then check whether that hash corresponds to the same hash for any of the
<a href=#21 id=21 data-nosnippet>21</a>/// patterns we're looking for.
<a href=#22 id=22 data-nosnippet>22</a>///
<a href=#23 id=23 data-nosnippet>23</a>/// A draw back of naively scaling Rabin-Karp to multiple patterns is that
<a href=#24 id=24 data-nosnippet>24</a>/// it requires all of the patterns to be the same length, which in turn
<a href=#25 id=25 data-nosnippet>25</a>/// corresponds to the number of bytes to hash. We adapt this to work for
<a href=#26 id=26 data-nosnippet>26</a>/// multiple patterns of varying size by fixing the number of bytes to hash
<a href=#27 id=27 data-nosnippet>27</a>/// to be the length of the smallest pattern. We also split the patterns into
<a href=#28 id=28 data-nosnippet>28</a>/// several buckets to hopefully make the confirmation step faster.
<a href=#29 id=29 data-nosnippet>29</a>///
<a href=#30 id=30 data-nosnippet>30</a>/// Wikipedia has a decent explanation, if a bit heavy on the theory:
<a href=#31 id=31 data-nosnippet>31</a>/// https://en.wikipedia.org/wiki/Rabin%E2%80%93Karp_algorithm
<a href=#32 id=32 data-nosnippet>32</a>///
<a href=#33 id=33 data-nosnippet>33</a>/// But ESMAJ provides something a bit more concrete:
<a href=#34 id=34 data-nosnippet>34</a>/// https://www-igm.univ-mlv.fr/~lecroq/string/node5.html
<a href=#35 id=35 data-nosnippet>35</a></span><span class="attr">#[derive(Clone, Debug)]
<a href=#36 id=36 data-nosnippet>36</a></span><span class="kw">pub</span>(<span class="kw">crate</span>) <span class="kw">struct </span>RabinKarp {
<a href=#37 id=37 data-nosnippet>37</a> <span class="doccomment">/// The patterns we're searching for.
<a href=#38 id=38 data-nosnippet>38</a> </span>patterns: Arc&lt;Patterns&gt;,
<a href=#39 id=39 data-nosnippet>39</a> <span class="doccomment">/// The order of patterns in each bucket is significant. Namely, they are
<a href=#40 id=40 data-nosnippet>40</a> /// arranged such that the first one to match is the correct match. This
<a href=#41 id=41 data-nosnippet>41</a> /// may not necessarily correspond to the order provided by the caller.
<a href=#42 id=42 data-nosnippet>42</a> /// For example, if leftmost-longest semantics are used, then the patterns
<a href=#43 id=43 data-nosnippet>43</a> /// are sorted by their length in descending order. If leftmost-first
<a href=#44 id=44 data-nosnippet>44</a> /// semantics are used, then the patterns are sorted by their pattern ID
<a href=#45 id=45 data-nosnippet>45</a> /// in ascending order (which corresponds to the caller's order).
<a href=#46 id=46 data-nosnippet>46</a> </span>buckets: Vec&lt;Vec&lt;(Hash, PatternID)&gt;&gt;,
<a href=#47 id=47 data-nosnippet>47</a> <span class="doccomment">/// The length of the hashing window. Generally, this corresponds to the
<a href=#48 id=48 data-nosnippet>48</a> /// length of the smallest pattern.
<a href=#49 id=49 data-nosnippet>49</a> </span>hash_len: usize,
<a href=#50 id=50 data-nosnippet>50</a> <span class="doccomment">/// The factor to subtract out of a hash before updating it with a new
<a href=#51 id=51 data-nosnippet>51</a> /// byte.
<a href=#52 id=52 data-nosnippet>52</a> </span>hash_2pow: usize,
<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">impl </span>RabinKarp {
<a href=#56 id=56 data-nosnippet>56</a> <span class="doccomment">/// Compile a new Rabin-Karp matcher from the patterns given.
<a href=#57 id=57 data-nosnippet>57</a> ///
<a href=#58 id=58 data-nosnippet>58</a> /// This panics if any of the patterns in the collection are empty, or if
<a href=#59 id=59 data-nosnippet>59</a> /// the collection is itself empty.
<a href=#60 id=60 data-nosnippet>60</a> </span><span class="kw">pub</span>(<span class="kw">crate</span>) <span class="kw">fn </span>new(patterns: <span class="kw-2">&amp;</span>Arc&lt;Patterns&gt;) -&gt; RabinKarp {
<a href=#61 id=61 data-nosnippet>61</a> <span class="macro">assert!</span>(patterns.len() &gt;= <span class="number">1</span>);
<a href=#62 id=62 data-nosnippet>62</a> <span class="kw">let </span>hash_len = patterns.minimum_len();
<a href=#63 id=63 data-nosnippet>63</a> <span class="macro">assert!</span>(hash_len &gt;= <span class="number">1</span>);
<a href=#64 id=64 data-nosnippet>64</a>
<a href=#65 id=65 data-nosnippet>65</a> <span class="kw">let </span><span class="kw-2">mut </span>hash_2pow = <span class="number">1usize</span>;
<a href=#66 id=66 data-nosnippet>66</a> <span class="kw">for _ in </span><span class="number">1</span>..hash_len {
<a href=#67 id=67 data-nosnippet>67</a> hash_2pow = hash_2pow.wrapping_shl(<span class="number">1</span>);
<a href=#68 id=68 data-nosnippet>68</a> }
<a href=#69 id=69 data-nosnippet>69</a>
<a href=#70 id=70 data-nosnippet>70</a> <span class="kw">let </span><span class="kw-2">mut </span>rk = RabinKarp {
<a href=#71 id=71 data-nosnippet>71</a> patterns: Arc::clone(patterns),
<a href=#72 id=72 data-nosnippet>72</a> buckets: <span class="macro">vec!</span>[<span class="macro">vec!</span>[]; NUM_BUCKETS],
<a href=#73 id=73 data-nosnippet>73</a> hash_len,
<a href=#74 id=74 data-nosnippet>74</a> hash_2pow,
<a href=#75 id=75 data-nosnippet>75</a> };
<a href=#76 id=76 data-nosnippet>76</a> <span class="kw">for </span>(id, pat) <span class="kw">in </span>patterns.iter() {
<a href=#77 id=77 data-nosnippet>77</a> <span class="kw">let </span>hash = rk.hash(<span class="kw-2">&amp;</span>pat.bytes()[..rk.hash_len]);
<a href=#78 id=78 data-nosnippet>78</a> <span class="kw">let </span>bucket = hash % NUM_BUCKETS;
<a href=#79 id=79 data-nosnippet>79</a> rk.buckets[bucket].push((hash, id));
<a href=#80 id=80 data-nosnippet>80</a> }
<a href=#81 id=81 data-nosnippet>81</a> rk
<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">/// Return the first matching pattern in the given haystack, begining the
<a href=#85 id=85 data-nosnippet>85</a> /// search at `at`.
<a href=#86 id=86 data-nosnippet>86</a> </span><span class="kw">pub</span>(<span class="kw">crate</span>) <span class="kw">fn </span>find_at(
<a href=#87 id=87 data-nosnippet>87</a> <span class="kw-2">&amp;</span><span class="self">self</span>,
<a href=#88 id=88 data-nosnippet>88</a> haystack: <span class="kw-2">&amp;</span>[u8],
<a href=#89 id=89 data-nosnippet>89</a> <span class="kw-2">mut </span>at: usize,
<a href=#90 id=90 data-nosnippet>90</a> ) -&gt; <span class="prelude-ty">Option</span>&lt;Match&gt; {
<a href=#91 id=91 data-nosnippet>91</a> <span class="macro">assert_eq!</span>(NUM_BUCKETS, <span class="self">self</span>.buckets.len());
<a href=#92 id=92 data-nosnippet>92</a>
<a href=#93 id=93 data-nosnippet>93</a> <span class="kw">if </span>at + <span class="self">self</span>.hash_len &gt; haystack.len() {
<a href=#94 id=94 data-nosnippet>94</a> <span class="kw">return </span><span class="prelude-val">None</span>;
<a href=#95 id=95 data-nosnippet>95</a> }
<a href=#96 id=96 data-nosnippet>96</a> <span class="kw">let </span><span class="kw-2">mut </span>hash = <span class="self">self</span>.hash(<span class="kw-2">&amp;</span>haystack[at..at + <span class="self">self</span>.hash_len]);
<a href=#97 id=97 data-nosnippet>97</a> <span class="kw">loop </span>{
<a href=#98 id=98 data-nosnippet>98</a> <span class="kw">let </span>bucket = <span class="kw-2">&amp;</span><span class="self">self</span>.buckets[hash % NUM_BUCKETS];
<a href=#99 id=99 data-nosnippet>99</a> <span class="kw">for </span><span class="kw-2">&amp;</span>(phash, pid) <span class="kw">in </span>bucket {
<a href=#100 id=100 data-nosnippet>100</a> <span class="kw">if </span>phash == hash {
<a href=#101 id=101 data-nosnippet>101</a> <span class="kw">if let </span><span class="prelude-val">Some</span>(c) = <span class="self">self</span>.verify(pid, haystack, at) {
<a href=#102 id=102 data-nosnippet>102</a> <span class="kw">return </span><span class="prelude-val">Some</span>(c);
<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> <span class="kw">if </span>at + <span class="self">self</span>.hash_len &gt;= haystack.len() {
<a href=#107 id=107 data-nosnippet>107</a> <span class="kw">return </span><span class="prelude-val">None</span>;
<a href=#108 id=108 data-nosnippet>108</a> }
<a href=#109 id=109 data-nosnippet>109</a> hash = <span class="self">self</span>.update_hash(
<a href=#110 id=110 data-nosnippet>110</a> hash,
<a href=#111 id=111 data-nosnippet>111</a> haystack[at],
<a href=#112 id=112 data-nosnippet>112</a> haystack[at + <span class="self">self</span>.hash_len],
<a href=#113 id=113 data-nosnippet>113</a> );
<a href=#114 id=114 data-nosnippet>114</a> at += <span class="number">1</span>;
<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>
<a href=#118 id=118 data-nosnippet>118</a> <span class="doccomment">/// Returns the approximate total amount of heap used by this searcher, in
<a href=#119 id=119 data-nosnippet>119</a> /// units of bytes.
<a href=#120 id=120 data-nosnippet>120</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=#121 id=121 data-nosnippet>121</a> <span class="self">self</span>.buckets.len() * core::mem::size_of::&lt;Vec&lt;(Hash, PatternID)&gt;&gt;()
<a href=#122 id=122 data-nosnippet>122</a> + <span class="self">self</span>.patterns.len() * core::mem::size_of::&lt;(Hash, PatternID)&gt;()
<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="doccomment">/// Verify whether the pattern with the given id matches at
<a href=#126 id=126 data-nosnippet>126</a> /// `haystack[at..]`.
<a href=#127 id=127 data-nosnippet>127</a> ///
<a href=#128 id=128 data-nosnippet>128</a> /// We tag this function as `cold` because it helps improve codegen.
<a href=#129 id=129 data-nosnippet>129</a> /// Intuitively, it would seem like inlining it would be better. However,
<a href=#130 id=130 data-nosnippet>130</a> /// the only time this is called and a match is not found is when there
<a href=#131 id=131 data-nosnippet>131</a> /// there is a hash collision, or when a prefix of a pattern matches but
<a href=#132 id=132 data-nosnippet>132</a> /// the entire pattern doesn't match. This is hopefully fairly rare, and
<a href=#133 id=133 data-nosnippet>133</a> /// if it does occur a lot, it's going to be slow no matter what we do.
<a href=#134 id=134 data-nosnippet>134</a> </span><span class="attr">#[cold]
<a href=#135 id=135 data-nosnippet>135</a> </span><span class="kw">fn </span>verify(
<a href=#136 id=136 data-nosnippet>136</a> <span class="kw-2">&amp;</span><span class="self">self</span>,
<a href=#137 id=137 data-nosnippet>137</a> id: PatternID,
<a href=#138 id=138 data-nosnippet>138</a> haystack: <span class="kw-2">&amp;</span>[u8],
<a href=#139 id=139 data-nosnippet>139</a> at: usize,
<a href=#140 id=140 data-nosnippet>140</a> ) -&gt; <span class="prelude-ty">Option</span>&lt;Match&gt; {
<a href=#141 id=141 data-nosnippet>141</a> <span class="kw">let </span>pat = <span class="self">self</span>.patterns.get(id);
<a href=#142 id=142 data-nosnippet>142</a> <span class="kw">if </span>pat.is_prefix(<span class="kw-2">&amp;</span>haystack[at..]) {
<a href=#143 id=143 data-nosnippet>143</a> <span class="prelude-val">Some</span>(Match::new(id, at..at + pat.len()))
<a href=#144 id=144 data-nosnippet>144</a> } <span class="kw">else </span>{
<a href=#145 id=145 data-nosnippet>145</a> <span class="prelude-val">None
<a href=#146 id=146 data-nosnippet>146</a> </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> <span class="doccomment">/// Hash the given bytes.
<a href=#150 id=150 data-nosnippet>150</a> </span><span class="kw">fn </span>hash(<span class="kw-2">&amp;</span><span class="self">self</span>, bytes: <span class="kw-2">&amp;</span>[u8]) -&gt; Hash {
<a href=#151 id=151 data-nosnippet>151</a> <span class="macro">assert_eq!</span>(<span class="self">self</span>.hash_len, bytes.len());
<a href=#152 id=152 data-nosnippet>152</a>
<a href=#153 id=153 data-nosnippet>153</a> <span class="kw">let </span><span class="kw-2">mut </span>hash = <span class="number">0usize</span>;
<a href=#154 id=154 data-nosnippet>154</a> <span class="kw">for </span><span class="kw-2">&amp;</span>b <span class="kw">in </span>bytes {
<a href=#155 id=155 data-nosnippet>155</a> hash = hash.wrapping_shl(<span class="number">1</span>).wrapping_add(b <span class="kw">as </span>usize);
<a href=#156 id=156 data-nosnippet>156</a> }
<a href=#157 id=157 data-nosnippet>157</a> hash
<a href=#158 id=158 data-nosnippet>158</a> }
<a href=#159 id=159 data-nosnippet>159</a>
<a href=#160 id=160 data-nosnippet>160</a> <span class="doccomment">/// Update the hash given based on removing `old_byte` at the beginning
<a href=#161 id=161 data-nosnippet>161</a> /// of some byte string, and appending `new_byte` to the end of that same
<a href=#162 id=162 data-nosnippet>162</a> /// byte string.
<a href=#163 id=163 data-nosnippet>163</a> </span><span class="kw">fn </span>update_hash(<span class="kw-2">&amp;</span><span class="self">self</span>, prev: Hash, old_byte: u8, new_byte: u8) -&gt; Hash {
<a href=#164 id=164 data-nosnippet>164</a> prev.wrapping_sub((old_byte <span class="kw">as </span>usize).wrapping_mul(<span class="self">self</span>.hash_2pow))
<a href=#165 id=165 data-nosnippet>165</a> .wrapping_shl(<span class="number">1</span>)
<a href=#166 id=166 data-nosnippet>166</a> .wrapping_add(new_byte <span class="kw">as </span>usize)
<a href=#167 id=167 data-nosnippet>167</a> }
<a href=#168 id=168 data-nosnippet>168</a>}
</code></pre></div></section></main></body></html>

View File

@@ -0,0 +1,793 @@
<!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/packed/teddy/builder.rs`."><title>builder.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/packed/teddy/</div>builder.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> fmt::Debug,
<a href=#3 id=3 data-nosnippet>3</a> panic::{RefUnwindSafe, UnwindSafe},
<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="kw">use </span>alloc::sync::Arc;
<a href=#7 id=7 data-nosnippet>7</a>
<a href=#8 id=8 data-nosnippet>8</a><span class="kw">use </span><span class="kw">crate</span>::packed::{ext::Pointer, pattern::Patterns, teddy::generic::Match};
<a href=#9 id=9 data-nosnippet>9</a>
<a href=#10 id=10 data-nosnippet>10</a><span class="doccomment">/// A builder for constructing a Teddy matcher.
<a href=#11 id=11 data-nosnippet>11</a>///
<a href=#12 id=12 data-nosnippet>12</a>/// The builder primarily permits fine grained configuration of the Teddy
<a href=#13 id=13 data-nosnippet>13</a>/// matcher. Most options are made only available for testing/benchmarking
<a href=#14 id=14 data-nosnippet>14</a>/// purposes. In reality, options are automatically determined by the nature
<a href=#15 id=15 data-nosnippet>15</a>/// and number of patterns given to the builder.
<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</span>(<span class="kw">crate</span>) <span class="kw">struct </span>Builder {
<a href=#18 id=18 data-nosnippet>18</a> <span class="doccomment">/// When none, this is automatically determined. Otherwise, `false` means
<a href=#19 id=19 data-nosnippet>19</a> /// slim Teddy is used (8 buckets) and `true` means fat Teddy is used
<a href=#20 id=20 data-nosnippet>20</a> /// (16 buckets). Fat Teddy requires AVX2, so if that CPU feature isn't
<a href=#21 id=21 data-nosnippet>21</a> /// available and Fat Teddy was requested, no matcher will be built.
<a href=#22 id=22 data-nosnippet>22</a> </span>only_fat: <span class="prelude-ty">Option</span>&lt;bool&gt;,
<a href=#23 id=23 data-nosnippet>23</a> <span class="doccomment">/// When none, this is automatically determined. Otherwise, `false` means
<a href=#24 id=24 data-nosnippet>24</a> /// that 128-bit vectors will be used (up to SSSE3 instructions) where as
<a href=#25 id=25 data-nosnippet>25</a> /// `true` means that 256-bit vectors will be used. As with `fat`, if
<a href=#26 id=26 data-nosnippet>26</a> /// 256-bit vectors are requested and they aren't available, then a
<a href=#27 id=27 data-nosnippet>27</a> /// searcher will not be built.
<a href=#28 id=28 data-nosnippet>28</a> </span>only_256bit: <span class="prelude-ty">Option</span>&lt;bool&gt;,
<a href=#29 id=29 data-nosnippet>29</a> <span class="doccomment">/// When true (the default), the number of patterns will be used as a
<a href=#30 id=30 data-nosnippet>30</a> /// heuristic for refusing construction of a Teddy searcher. The point here
<a href=#31 id=31 data-nosnippet>31</a> /// is that too many patterns can overwhelm Teddy. But this can be disabled
<a href=#32 id=32 data-nosnippet>32</a> /// in cases where the caller knows better.
<a href=#33 id=33 data-nosnippet>33</a> </span>heuristic_pattern_limits: bool,
<a href=#34 id=34 data-nosnippet>34</a>}
<a href=#35 id=35 data-nosnippet>35</a>
<a href=#36 id=36 data-nosnippet>36</a><span class="kw">impl </span>Default <span class="kw">for </span>Builder {
<a href=#37 id=37 data-nosnippet>37</a> <span class="kw">fn </span>default() -&gt; Builder {
<a href=#38 id=38 data-nosnippet>38</a> Builder::new()
<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>
<a href=#42 id=42 data-nosnippet>42</a><span class="kw">impl </span>Builder {
<a href=#43 id=43 data-nosnippet>43</a> <span class="doccomment">/// Create a new builder for configuring a Teddy matcher.
<a href=#44 id=44 data-nosnippet>44</a> </span><span class="kw">pub</span>(<span class="kw">crate</span>) <span class="kw">fn </span>new() -&gt; Builder {
<a href=#45 id=45 data-nosnippet>45</a> Builder {
<a href=#46 id=46 data-nosnippet>46</a> only_fat: <span class="prelude-val">None</span>,
<a href=#47 id=47 data-nosnippet>47</a> only_256bit: <span class="prelude-val">None</span>,
<a href=#48 id=48 data-nosnippet>48</a> heuristic_pattern_limits: <span class="bool-val">true</span>,
<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>
<a href=#52 id=52 data-nosnippet>52</a> <span class="doccomment">/// Build a matcher for the set of patterns given. If a matcher could not
<a href=#53 id=53 data-nosnippet>53</a> /// be built, then `None` is returned.
<a href=#54 id=54 data-nosnippet>54</a> ///
<a href=#55 id=55 data-nosnippet>55</a> /// Generally, a matcher isn't built if the necessary CPU features aren't
<a href=#56 id=56 data-nosnippet>56</a> /// available, an unsupported target or if the searcher is believed to be
<a href=#57 id=57 data-nosnippet>57</a> /// slower than standard techniques (i.e., if there are too many literals).
<a href=#58 id=58 data-nosnippet>58</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>, patterns: Arc&lt;Patterns&gt;) -&gt; <span class="prelude-ty">Option</span>&lt;Searcher&gt; {
<a href=#59 id=59 data-nosnippet>59</a> <span class="self">self</span>.build_imp(patterns)
<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="doccomment">/// Require the use of Fat (true) or Slim (false) Teddy. Fat Teddy uses
<a href=#63 id=63 data-nosnippet>63</a> /// 16 buckets where as Slim Teddy uses 8 buckets. More buckets are useful
<a href=#64 id=64 data-nosnippet>64</a> /// for a larger set of literals.
<a href=#65 id=65 data-nosnippet>65</a> ///
<a href=#66 id=66 data-nosnippet>66</a> /// `None` is the default, which results in an automatic selection based
<a href=#67 id=67 data-nosnippet>67</a> /// on the number of literals and available CPU features.
<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>only_fat(<span class="kw-2">&amp;mut </span><span class="self">self</span>, yes: <span class="prelude-ty">Option</span>&lt;bool&gt;) -&gt; <span class="kw-2">&amp;mut </span>Builder {
<a href=#69 id=69 data-nosnippet>69</a> <span class="self">self</span>.only_fat = yes;
<a href=#70 id=70 data-nosnippet>70</a> <span class="self">self
<a href=#71 id=71 data-nosnippet>71</a> </span>}
<a href=#72 id=72 data-nosnippet>72</a>
<a href=#73 id=73 data-nosnippet>73</a> <span class="doccomment">/// Request the use of 256-bit vectors (true) or 128-bit vectors (false).
<a href=#74 id=74 data-nosnippet>74</a> /// Generally, a larger vector size is better since it either permits
<a href=#75 id=75 data-nosnippet>75</a> /// matching more patterns or matching more bytes in the haystack at once.
<a href=#76 id=76 data-nosnippet>76</a> ///
<a href=#77 id=77 data-nosnippet>77</a> /// `None` is the default, which results in an automatic selection based on
<a href=#78 id=78 data-nosnippet>78</a> /// the number of literals and available CPU features.
<a href=#79 id=79 data-nosnippet>79</a> </span><span class="kw">pub</span>(<span class="kw">crate</span>) <span class="kw">fn </span>only_256bit(<span class="kw-2">&amp;mut </span><span class="self">self</span>, yes: <span class="prelude-ty">Option</span>&lt;bool&gt;) -&gt; <span class="kw-2">&amp;mut </span>Builder {
<a href=#80 id=80 data-nosnippet>80</a> <span class="self">self</span>.only_256bit = yes;
<a href=#81 id=81 data-nosnippet>81</a> <span class="self">self
<a href=#82 id=82 data-nosnippet>82</a> </span>}
<a href=#83 id=83 data-nosnippet>83</a>
<a href=#84 id=84 data-nosnippet>84</a> <span class="doccomment">/// Request that heuristic limitations on the number of patterns be
<a href=#85 id=85 data-nosnippet>85</a> /// employed. This useful to disable for benchmarking where one wants to
<a href=#86 id=86 data-nosnippet>86</a> /// explore how Teddy performs on large number of patterns even if the
<a href=#87 id=87 data-nosnippet>87</a> /// heuristics would otherwise refuse construction.
<a href=#88 id=88 data-nosnippet>88</a> ///
<a href=#89 id=89 data-nosnippet>89</a> /// This is enabled by default.
<a href=#90 id=90 data-nosnippet>90</a> </span><span class="kw">pub</span>(<span class="kw">crate</span>) <span class="kw">fn </span>heuristic_pattern_limits(
<a href=#91 id=91 data-nosnippet>91</a> <span class="kw-2">&amp;mut </span><span class="self">self</span>,
<a href=#92 id=92 data-nosnippet>92</a> yes: bool,
<a href=#93 id=93 data-nosnippet>93</a> ) -&gt; <span class="kw-2">&amp;mut </span>Builder {
<a href=#94 id=94 data-nosnippet>94</a> <span class="self">self</span>.heuristic_pattern_limits = yes;
<a href=#95 id=95 data-nosnippet>95</a> <span class="self">self
<a href=#96 id=96 data-nosnippet>96</a> </span>}
<a href=#97 id=97 data-nosnippet>97</a>
<a href=#98 id=98 data-nosnippet>98</a> <span class="kw">fn </span>build_imp(<span class="kw-2">&amp;</span><span class="self">self</span>, patterns: Arc&lt;Patterns&gt;) -&gt; <span class="prelude-ty">Option</span>&lt;Searcher&gt; {
<a href=#99 id=99 data-nosnippet>99</a> <span class="kw">let </span>patlimit = <span class="self">self</span>.heuristic_pattern_limits;
<a href=#100 id=100 data-nosnippet>100</a> <span class="comment">// There's no particular reason why we limit ourselves to little endian
<a href=#101 id=101 data-nosnippet>101</a> // here, but it seems likely that some parts of Teddy as they are
<a href=#102 id=102 data-nosnippet>102</a> // currently written (e.g., the uses of `trailing_zeros`) are likely
<a href=#103 id=103 data-nosnippet>103</a> // wrong on non-little-endian targets. Such things are likely easy to
<a href=#104 id=104 data-nosnippet>104</a> // fix, but at the time of writing (2023/09/18), I actually do not know
<a href=#105 id=105 data-nosnippet>105</a> // how to test this code on a big-endian target. So for now, we're
<a href=#106 id=106 data-nosnippet>106</a> // conservative and just bail out.
<a href=#107 id=107 data-nosnippet>107</a> </span><span class="kw">if </span>!<span class="macro">cfg!</span>(target_endian = <span class="string">"little"</span>) {
<a href=#108 id=108 data-nosnippet>108</a> <span class="macro">debug!</span>(<span class="string">"skipping Teddy because target isn't little endian"</span>);
<a href=#109 id=109 data-nosnippet>109</a> <span class="kw">return </span><span class="prelude-val">None</span>;
<a href=#110 id=110 data-nosnippet>110</a> }
<a href=#111 id=111 data-nosnippet>111</a> <span class="comment">// Too many patterns will overwhelm Teddy and likely lead to slow
<a href=#112 id=112 data-nosnippet>112</a> // downs, typically in the verification step.
<a href=#113 id=113 data-nosnippet>113</a> </span><span class="kw">if </span>patlimit &amp;&amp; patterns.len() &gt; <span class="number">64 </span>{
<a href=#114 id=114 data-nosnippet>114</a> <span class="macro">debug!</span>(<span class="string">"skipping Teddy because of too many patterns"</span>);
<a href=#115 id=115 data-nosnippet>115</a> <span class="kw">return </span><span class="prelude-val">None</span>;
<a href=#116 id=116 data-nosnippet>116</a> }
<a href=#117 id=117 data-nosnippet>117</a>
<a href=#118 id=118 data-nosnippet>118</a> <span class="attr">#[cfg(all(target_arch = <span class="string">"x86_64"</span>, target_feature = <span class="string">"sse2"</span>))]
<a href=#119 id=119 data-nosnippet>119</a> </span>{
<a href=#120 id=120 data-nosnippet>120</a> <span class="kw">use </span><span class="self">self</span>::x86_64::{FatAVX2, SlimAVX2, SlimSSSE3};
<a href=#121 id=121 data-nosnippet>121</a>
<a href=#122 id=122 data-nosnippet>122</a> <span class="kw">let </span>mask_len = core::cmp::min(<span class="number">4</span>, patterns.minimum_len());
<a href=#123 id=123 data-nosnippet>123</a> <span class="kw">let </span>beefy = patterns.len() &gt; <span class="number">32</span>;
<a href=#124 id=124 data-nosnippet>124</a> <span class="kw">let </span>has_avx2 = <span class="self">self</span>::x86_64::is_available_avx2();
<a href=#125 id=125 data-nosnippet>125</a> <span class="kw">let </span>has_ssse3 = has_avx2 || <span class="self">self</span>::x86_64::is_available_ssse3();
<a href=#126 id=126 data-nosnippet>126</a> <span class="kw">let </span>use_avx2 = <span class="kw">if </span><span class="self">self</span>.only_256bit == <span class="prelude-val">Some</span>(<span class="bool-val">true</span>) {
<a href=#127 id=127 data-nosnippet>127</a> <span class="kw">if </span>!has_avx2 {
<a href=#128 id=128 data-nosnippet>128</a> <span class="macro">debug!</span>(
<a href=#129 id=129 data-nosnippet>129</a> <span class="string">"skipping Teddy because avx2 was demanded but unavailable"
<a href=#130 id=130 data-nosnippet>130</a> </span>);
<a href=#131 id=131 data-nosnippet>131</a> <span class="kw">return </span><span class="prelude-val">None</span>;
<a href=#132 id=132 data-nosnippet>132</a> }
<a href=#133 id=133 data-nosnippet>133</a> <span class="bool-val">true
<a href=#134 id=134 data-nosnippet>134</a> </span>} <span class="kw">else if </span><span class="self">self</span>.only_256bit == <span class="prelude-val">Some</span>(<span class="bool-val">false</span>) {
<a href=#135 id=135 data-nosnippet>135</a> <span class="kw">if </span>!has_ssse3 {
<a href=#136 id=136 data-nosnippet>136</a> <span class="macro">debug!</span>(
<a href=#137 id=137 data-nosnippet>137</a> <span class="string">"skipping Teddy because ssse3 was demanded but unavailable"
<a href=#138 id=138 data-nosnippet>138</a> </span>);
<a href=#139 id=139 data-nosnippet>139</a> <span class="kw">return </span><span class="prelude-val">None</span>;
<a href=#140 id=140 data-nosnippet>140</a> }
<a href=#141 id=141 data-nosnippet>141</a> <span class="bool-val">false
<a href=#142 id=142 data-nosnippet>142</a> </span>} <span class="kw">else if </span>!has_ssse3 &amp;&amp; !has_avx2 {
<a href=#143 id=143 data-nosnippet>143</a> <span class="macro">debug!</span>(
<a href=#144 id=144 data-nosnippet>144</a> <span class="string">"skipping Teddy because ssse3 and avx2 are unavailable"
<a href=#145 id=145 data-nosnippet>145</a> </span>);
<a href=#146 id=146 data-nosnippet>146</a> <span class="kw">return </span><span class="prelude-val">None</span>;
<a href=#147 id=147 data-nosnippet>147</a> } <span class="kw">else </span>{
<a href=#148 id=148 data-nosnippet>148</a> has_avx2
<a href=#149 id=149 data-nosnippet>149</a> };
<a href=#150 id=150 data-nosnippet>150</a> <span class="kw">let </span>fat = <span class="kw">match </span><span class="self">self</span>.only_fat {
<a href=#151 id=151 data-nosnippet>151</a> <span class="prelude-val">None </span>=&gt; use_avx2 &amp;&amp; beefy,
<a href=#152 id=152 data-nosnippet>152</a> <span class="prelude-val">Some</span>(<span class="bool-val">false</span>) =&gt; <span class="bool-val">false</span>,
<a href=#153 id=153 data-nosnippet>153</a> <span class="prelude-val">Some</span>(<span class="bool-val">true</span>) <span class="kw">if </span>!use_avx2 =&gt; {
<a href=#154 id=154 data-nosnippet>154</a> <span class="macro">debug!</span>(
<a href=#155 id=155 data-nosnippet>155</a> <span class="string">"skipping Teddy because fat was demanded, but fat \
<a href=#156 id=156 data-nosnippet>156</a> Teddy requires avx2 which is unavailable"
<a href=#157 id=157 data-nosnippet>157</a> </span>);
<a href=#158 id=158 data-nosnippet>158</a> <span class="kw">return </span><span class="prelude-val">None</span>;
<a href=#159 id=159 data-nosnippet>159</a> }
<a href=#160 id=160 data-nosnippet>160</a> <span class="prelude-val">Some</span>(<span class="bool-val">true</span>) =&gt; <span class="bool-val">true</span>,
<a href=#161 id=161 data-nosnippet>161</a> };
<a href=#162 id=162 data-nosnippet>162</a> <span class="comment">// Just like for aarch64, it's possible that too many patterns will
<a href=#163 id=163 data-nosnippet>163</a> // overhwelm Teddy. Unlike aarch64 though, we have Fat teddy which
<a href=#164 id=164 data-nosnippet>164</a> // helps things scale a bit more by spreading patterns over more
<a href=#165 id=165 data-nosnippet>165</a> // buckets.
<a href=#166 id=166 data-nosnippet>166</a> //
<a href=#167 id=167 data-nosnippet>167</a> // These thresholds were determined by looking at the measurements
<a href=#168 id=168 data-nosnippet>168</a> // for the rust/aho-corasick/packed/leftmost-first and
<a href=#169 id=169 data-nosnippet>169</a> // rust/aho-corasick/dfa/leftmost-first engines on the `teddy/`
<a href=#170 id=170 data-nosnippet>170</a> // benchmarks.
<a href=#171 id=171 data-nosnippet>171</a> </span><span class="kw">if </span>patlimit &amp;&amp; mask_len == <span class="number">1 </span>&amp;&amp; patterns.len() &gt; <span class="number">16 </span>{
<a href=#172 id=172 data-nosnippet>172</a> <span class="macro">debug!</span>(
<a href=#173 id=173 data-nosnippet>173</a> <span class="string">"skipping Teddy (mask len: 1) because there are \
<a href=#174 id=174 data-nosnippet>174</a> too many patterns"</span>,
<a href=#175 id=175 data-nosnippet>175</a> );
<a href=#176 id=176 data-nosnippet>176</a> <span class="kw">return </span><span class="prelude-val">None</span>;
<a href=#177 id=177 data-nosnippet>177</a> }
<a href=#178 id=178 data-nosnippet>178</a> <span class="kw">match </span>(mask_len, use_avx2, fat) {
<a href=#179 id=179 data-nosnippet>179</a> (<span class="number">1</span>, <span class="bool-val">false</span>, <span class="kw">_</span>) =&gt; {
<a href=#180 id=180 data-nosnippet>180</a> <span class="macro">debug!</span>(<span class="string">"Teddy choice: 128-bit slim, 1 byte"</span>);
<a href=#181 id=181 data-nosnippet>181</a> SlimSSSE3::&lt;<span class="number">1</span>&gt;::new(<span class="kw-2">&amp;</span>patterns)
<a href=#182 id=182 data-nosnippet>182</a> }
<a href=#183 id=183 data-nosnippet>183</a> (<span class="number">1</span>, <span class="bool-val">true</span>, <span class="bool-val">false</span>) =&gt; {
<a href=#184 id=184 data-nosnippet>184</a> <span class="macro">debug!</span>(<span class="string">"Teddy choice: 256-bit slim, 1 byte"</span>);
<a href=#185 id=185 data-nosnippet>185</a> SlimAVX2::&lt;<span class="number">1</span>&gt;::new(<span class="kw-2">&amp;</span>patterns)
<a href=#186 id=186 data-nosnippet>186</a> }
<a href=#187 id=187 data-nosnippet>187</a> (<span class="number">1</span>, <span class="bool-val">true</span>, <span class="bool-val">true</span>) =&gt; {
<a href=#188 id=188 data-nosnippet>188</a> <span class="macro">debug!</span>(<span class="string">"Teddy choice: 256-bit fat, 1 byte"</span>);
<a href=#189 id=189 data-nosnippet>189</a> FatAVX2::&lt;<span class="number">1</span>&gt;::new(<span class="kw-2">&amp;</span>patterns)
<a href=#190 id=190 data-nosnippet>190</a> }
<a href=#191 id=191 data-nosnippet>191</a> (<span class="number">2</span>, <span class="bool-val">false</span>, <span class="kw">_</span>) =&gt; {
<a href=#192 id=192 data-nosnippet>192</a> <span class="macro">debug!</span>(<span class="string">"Teddy choice: 128-bit slim, 2 bytes"</span>);
<a href=#193 id=193 data-nosnippet>193</a> SlimSSSE3::&lt;<span class="number">2</span>&gt;::new(<span class="kw-2">&amp;</span>patterns)
<a href=#194 id=194 data-nosnippet>194</a> }
<a href=#195 id=195 data-nosnippet>195</a> (<span class="number">2</span>, <span class="bool-val">true</span>, <span class="bool-val">false</span>) =&gt; {
<a href=#196 id=196 data-nosnippet>196</a> <span class="macro">debug!</span>(<span class="string">"Teddy choice: 256-bit slim, 2 bytes"</span>);
<a href=#197 id=197 data-nosnippet>197</a> SlimAVX2::&lt;<span class="number">2</span>&gt;::new(<span class="kw-2">&amp;</span>patterns)
<a href=#198 id=198 data-nosnippet>198</a> }
<a href=#199 id=199 data-nosnippet>199</a> (<span class="number">2</span>, <span class="bool-val">true</span>, <span class="bool-val">true</span>) =&gt; {
<a href=#200 id=200 data-nosnippet>200</a> <span class="macro">debug!</span>(<span class="string">"Teddy choice: 256-bit fat, 2 bytes"</span>);
<a href=#201 id=201 data-nosnippet>201</a> FatAVX2::&lt;<span class="number">2</span>&gt;::new(<span class="kw-2">&amp;</span>patterns)
<a href=#202 id=202 data-nosnippet>202</a> }
<a href=#203 id=203 data-nosnippet>203</a> (<span class="number">3</span>, <span class="bool-val">false</span>, <span class="kw">_</span>) =&gt; {
<a href=#204 id=204 data-nosnippet>204</a> <span class="macro">debug!</span>(<span class="string">"Teddy choice: 128-bit slim, 3 bytes"</span>);
<a href=#205 id=205 data-nosnippet>205</a> SlimSSSE3::&lt;<span class="number">3</span>&gt;::new(<span class="kw-2">&amp;</span>patterns)
<a href=#206 id=206 data-nosnippet>206</a> }
<a href=#207 id=207 data-nosnippet>207</a> (<span class="number">3</span>, <span class="bool-val">true</span>, <span class="bool-val">false</span>) =&gt; {
<a href=#208 id=208 data-nosnippet>208</a> <span class="macro">debug!</span>(<span class="string">"Teddy choice: 256-bit slim, 3 bytes"</span>);
<a href=#209 id=209 data-nosnippet>209</a> SlimAVX2::&lt;<span class="number">3</span>&gt;::new(<span class="kw-2">&amp;</span>patterns)
<a href=#210 id=210 data-nosnippet>210</a> }
<a href=#211 id=211 data-nosnippet>211</a> (<span class="number">3</span>, <span class="bool-val">true</span>, <span class="bool-val">true</span>) =&gt; {
<a href=#212 id=212 data-nosnippet>212</a> <span class="macro">debug!</span>(<span class="string">"Teddy choice: 256-bit fat, 3 bytes"</span>);
<a href=#213 id=213 data-nosnippet>213</a> FatAVX2::&lt;<span class="number">3</span>&gt;::new(<span class="kw-2">&amp;</span>patterns)
<a href=#214 id=214 data-nosnippet>214</a> }
<a href=#215 id=215 data-nosnippet>215</a> (<span class="number">4</span>, <span class="bool-val">false</span>, <span class="kw">_</span>) =&gt; {
<a href=#216 id=216 data-nosnippet>216</a> <span class="macro">debug!</span>(<span class="string">"Teddy choice: 128-bit slim, 4 bytes"</span>);
<a href=#217 id=217 data-nosnippet>217</a> SlimSSSE3::&lt;<span class="number">4</span>&gt;::new(<span class="kw-2">&amp;</span>patterns)
<a href=#218 id=218 data-nosnippet>218</a> }
<a href=#219 id=219 data-nosnippet>219</a> (<span class="number">4</span>, <span class="bool-val">true</span>, <span class="bool-val">false</span>) =&gt; {
<a href=#220 id=220 data-nosnippet>220</a> <span class="macro">debug!</span>(<span class="string">"Teddy choice: 256-bit slim, 4 bytes"</span>);
<a href=#221 id=221 data-nosnippet>221</a> SlimAVX2::&lt;<span class="number">4</span>&gt;::new(<span class="kw-2">&amp;</span>patterns)
<a href=#222 id=222 data-nosnippet>222</a> }
<a href=#223 id=223 data-nosnippet>223</a> (<span class="number">4</span>, <span class="bool-val">true</span>, <span class="bool-val">true</span>) =&gt; {
<a href=#224 id=224 data-nosnippet>224</a> <span class="macro">debug!</span>(<span class="string">"Teddy choice: 256-bit fat, 4 bytes"</span>);
<a href=#225 id=225 data-nosnippet>225</a> FatAVX2::&lt;<span class="number">4</span>&gt;::new(<span class="kw-2">&amp;</span>patterns)
<a href=#226 id=226 data-nosnippet>226</a> }
<a href=#227 id=227 data-nosnippet>227</a> <span class="kw">_ </span>=&gt; {
<a href=#228 id=228 data-nosnippet>228</a> <span class="macro">debug!</span>(<span class="string">"no supported Teddy configuration found"</span>);
<a href=#229 id=229 data-nosnippet>229</a> <span class="prelude-val">None
<a href=#230 id=230 data-nosnippet>230</a> </span>}
<a href=#231 id=231 data-nosnippet>231</a> }
<a href=#232 id=232 data-nosnippet>232</a> }
<a href=#233 id=233 data-nosnippet>233</a> <span class="attr">#[cfg(all(
<a href=#234 id=234 data-nosnippet>234</a> target_arch = <span class="string">"aarch64"</span>,
<a href=#235 id=235 data-nosnippet>235</a> target_feature = <span class="string">"neon"</span>,
<a href=#236 id=236 data-nosnippet>236</a> target_endian = <span class="string">"little"
<a href=#237 id=237 data-nosnippet>237</a> </span>))]
<a href=#238 id=238 data-nosnippet>238</a> </span>{
<a href=#239 id=239 data-nosnippet>239</a> <span class="kw">use </span><span class="self">self</span>::aarch64::SlimNeon;
<a href=#240 id=240 data-nosnippet>240</a>
<a href=#241 id=241 data-nosnippet>241</a> <span class="kw">let </span>mask_len = core::cmp::min(<span class="number">4</span>, patterns.minimum_len());
<a href=#242 id=242 data-nosnippet>242</a> <span class="kw">if </span><span class="self">self</span>.only_256bit == <span class="prelude-val">Some</span>(<span class="bool-val">true</span>) {
<a href=#243 id=243 data-nosnippet>243</a> <span class="macro">debug!</span>(
<a href=#244 id=244 data-nosnippet>244</a> <span class="string">"skipping Teddy because 256-bits were demanded \
<a href=#245 id=245 data-nosnippet>245</a> but unavailable"
<a href=#246 id=246 data-nosnippet>246</a> </span>);
<a href=#247 id=247 data-nosnippet>247</a> <span class="kw">return </span><span class="prelude-val">None</span>;
<a href=#248 id=248 data-nosnippet>248</a> }
<a href=#249 id=249 data-nosnippet>249</a> <span class="kw">if </span><span class="self">self</span>.only_fat == <span class="prelude-val">Some</span>(<span class="bool-val">true</span>) {
<a href=#250 id=250 data-nosnippet>250</a> <span class="macro">debug!</span>(
<a href=#251 id=251 data-nosnippet>251</a> <span class="string">"skipping Teddy because fat was demanded but unavailable"
<a href=#252 id=252 data-nosnippet>252</a> </span>);
<a href=#253 id=253 data-nosnippet>253</a> }
<a href=#254 id=254 data-nosnippet>254</a> <span class="comment">// Since we don't have Fat teddy in aarch64 (I think we'd want at
<a href=#255 id=255 data-nosnippet>255</a> // least 256-bit vectors for that), we need to be careful not to
<a href=#256 id=256 data-nosnippet>256</a> // allow too many patterns as it might overwhelm Teddy. Generally
<a href=#257 id=257 data-nosnippet>257</a> // speaking, as the mask length goes up, the more patterns we can
<a href=#258 id=258 data-nosnippet>258</a> // handle because the mask length results in fewer candidates
<a href=#259 id=259 data-nosnippet>259</a> // generated.
<a href=#260 id=260 data-nosnippet>260</a> //
<a href=#261 id=261 data-nosnippet>261</a> // These thresholds were determined by looking at the measurements
<a href=#262 id=262 data-nosnippet>262</a> // for the rust/aho-corasick/packed/leftmost-first and
<a href=#263 id=263 data-nosnippet>263</a> // rust/aho-corasick/dfa/leftmost-first engines on the `teddy/`
<a href=#264 id=264 data-nosnippet>264</a> // benchmarks.
<a href=#265 id=265 data-nosnippet>265</a> </span><span class="kw">match </span>mask_len {
<a href=#266 id=266 data-nosnippet>266</a> <span class="number">1 </span>=&gt; {
<a href=#267 id=267 data-nosnippet>267</a> <span class="kw">if </span>patlimit &amp;&amp; patterns.len() &gt; <span class="number">16 </span>{
<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">"skipping Teddy (mask len: 1) because there are \
<a href=#270 id=270 data-nosnippet>270</a> too many patterns"</span>,
<a href=#271 id=271 data-nosnippet>271</a> );
<a href=#272 id=272 data-nosnippet>272</a> }
<a href=#273 id=273 data-nosnippet>273</a> <span class="macro">debug!</span>(<span class="string">"Teddy choice: 128-bit slim, 1 byte"</span>);
<a href=#274 id=274 data-nosnippet>274</a> SlimNeon::&lt;<span class="number">1</span>&gt;::new(<span class="kw-2">&amp;</span>patterns)
<a href=#275 id=275 data-nosnippet>275</a> }
<a href=#276 id=276 data-nosnippet>276</a> <span class="number">2 </span>=&gt; {
<a href=#277 id=277 data-nosnippet>277</a> <span class="kw">if </span>patlimit &amp;&amp; patterns.len() &gt; <span class="number">32 </span>{
<a href=#278 id=278 data-nosnippet>278</a> <span class="macro">debug!</span>(
<a href=#279 id=279 data-nosnippet>279</a> <span class="string">"skipping Teddy (mask len: 2) because there are \
<a href=#280 id=280 data-nosnippet>280</a> too many patterns"</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="macro">debug!</span>(<span class="string">"Teddy choice: 128-bit slim, 2 bytes"</span>);
<a href=#284 id=284 data-nosnippet>284</a> SlimNeon::&lt;<span class="number">2</span>&gt;::new(<span class="kw-2">&amp;</span>patterns)
<a href=#285 id=285 data-nosnippet>285</a> }
<a href=#286 id=286 data-nosnippet>286</a> <span class="number">3 </span>=&gt; {
<a href=#287 id=287 data-nosnippet>287</a> <span class="kw">if </span>patlimit &amp;&amp; patterns.len() &gt; <span class="number">48 </span>{
<a href=#288 id=288 data-nosnippet>288</a> <span class="macro">debug!</span>(
<a href=#289 id=289 data-nosnippet>289</a> <span class="string">"skipping Teddy (mask len: 3) because there are \
<a href=#290 id=290 data-nosnippet>290</a> too many patterns"</span>,
<a href=#291 id=291 data-nosnippet>291</a> );
<a href=#292 id=292 data-nosnippet>292</a> }
<a href=#293 id=293 data-nosnippet>293</a> <span class="macro">debug!</span>(<span class="string">"Teddy choice: 128-bit slim, 3 bytes"</span>);
<a href=#294 id=294 data-nosnippet>294</a> SlimNeon::&lt;<span class="number">3</span>&gt;::new(<span class="kw-2">&amp;</span>patterns)
<a href=#295 id=295 data-nosnippet>295</a> }
<a href=#296 id=296 data-nosnippet>296</a> <span class="number">4 </span>=&gt; {
<a href=#297 id=297 data-nosnippet>297</a> <span class="macro">debug!</span>(<span class="string">"Teddy choice: 128-bit slim, 4 bytes"</span>);
<a href=#298 id=298 data-nosnippet>298</a> SlimNeon::&lt;<span class="number">4</span>&gt;::new(<span class="kw-2">&amp;</span>patterns)
<a href=#299 id=299 data-nosnippet>299</a> }
<a href=#300 id=300 data-nosnippet>300</a> <span class="kw">_ </span>=&gt; {
<a href=#301 id=301 data-nosnippet>301</a> <span class="macro">debug!</span>(<span class="string">"no supported Teddy configuration found"</span>);
<a href=#302 id=302 data-nosnippet>302</a> <span class="prelude-val">None
<a href=#303 id=303 data-nosnippet>303</a> </span>}
<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> <span class="attr">#[cfg(not(any(
<a href=#307 id=307 data-nosnippet>307</a> all(target_arch = <span class="string">"x86_64"</span>, target_feature = <span class="string">"sse2"</span>),
<a href=#308 id=308 data-nosnippet>308</a> all(
<a href=#309 id=309 data-nosnippet>309</a> target_arch = <span class="string">"aarch64"</span>,
<a href=#310 id=310 data-nosnippet>310</a> target_feature = <span class="string">"neon"</span>,
<a href=#311 id=311 data-nosnippet>311</a> target_endian = <span class="string">"little"
<a href=#312 id=312 data-nosnippet>312</a> </span>)
<a href=#313 id=313 data-nosnippet>313</a> )))]
<a href=#314 id=314 data-nosnippet>314</a> </span>{
<a href=#315 id=315 data-nosnippet>315</a> <span class="prelude-val">None
<a href=#316 id=316 data-nosnippet>316</a> </span>}
<a href=#317 id=317 data-nosnippet>317</a> }
<a href=#318 id=318 data-nosnippet>318</a>}
<a href=#319 id=319 data-nosnippet>319</a>
<a href=#320 id=320 data-nosnippet>320</a><span class="doccomment">/// A searcher that dispatches to one of several possible Teddy variants.
<a href=#321 id=321 data-nosnippet>321</a></span><span class="attr">#[derive(Clone, Debug)]
<a href=#322 id=322 data-nosnippet>322</a></span><span class="kw">pub</span>(<span class="kw">crate</span>) <span class="kw">struct </span>Searcher {
<a href=#323 id=323 data-nosnippet>323</a> <span class="doccomment">/// The Teddy variant we use. We use dynamic dispatch under the theory that
<a href=#324 id=324 data-nosnippet>324</a> /// it results in better codegen then a enum, although this is a specious
<a href=#325 id=325 data-nosnippet>325</a> /// claim.
<a href=#326 id=326 data-nosnippet>326</a> ///
<a href=#327 id=327 data-nosnippet>327</a> /// This `Searcher` is essentially a wrapper for a `SearcherT` trait
<a href=#328 id=328 data-nosnippet>328</a> /// object. We just make `memory_usage` and `minimum_len` available without
<a href=#329 id=329 data-nosnippet>329</a> /// going through dynamic dispatch.
<a href=#330 id=330 data-nosnippet>330</a> </span>imp: Arc&lt;<span class="kw">dyn </span>SearcherT&gt;,
<a href=#331 id=331 data-nosnippet>331</a> <span class="doccomment">/// Total heap memory used by the Teddy variant.
<a href=#332 id=332 data-nosnippet>332</a> </span>memory_usage: usize,
<a href=#333 id=333 data-nosnippet>333</a> <span class="doccomment">/// The minimum haystack length this searcher can handle. It is intended
<a href=#334 id=334 data-nosnippet>334</a> /// for callers to use some other search routine (such as Rabin-Karp) in
<a href=#335 id=335 data-nosnippet>335</a> /// cases where the haystack (or remainer of the haystack) is too short.
<a href=#336 id=336 data-nosnippet>336</a> </span>minimum_len: usize,
<a href=#337 id=337 data-nosnippet>337</a>}
<a href=#338 id=338 data-nosnippet>338</a>
<a href=#339 id=339 data-nosnippet>339</a><span class="kw">impl </span>Searcher {
<a href=#340 id=340 data-nosnippet>340</a> <span class="doccomment">/// Look for the leftmost occurrence of any pattern in this search in the
<a href=#341 id=341 data-nosnippet>341</a> /// given haystack starting at the given position.
<a href=#342 id=342 data-nosnippet>342</a> ///
<a href=#343 id=343 data-nosnippet>343</a> /// # Panics
<a href=#344 id=344 data-nosnippet>344</a> ///
<a href=#345 id=345 data-nosnippet>345</a> /// This panics when `haystack[at..].len()` is less than the minimum length
<a href=#346 id=346 data-nosnippet>346</a> /// for this haystack.
<a href=#347 id=347 data-nosnippet>347</a> </span><span class="attr">#[inline(always)]
<a href=#348 id=348 data-nosnippet>348</a> </span><span class="kw">pub</span>(<span class="kw">crate</span>) <span class="kw">fn </span>find(
<a href=#349 id=349 data-nosnippet>349</a> <span class="kw-2">&amp;</span><span class="self">self</span>,
<a href=#350 id=350 data-nosnippet>350</a> haystack: <span class="kw-2">&amp;</span>[u8],
<a href=#351 id=351 data-nosnippet>351</a> at: usize,
<a href=#352 id=352 data-nosnippet>352</a> ) -&gt; <span class="prelude-ty">Option</span>&lt;<span class="kw">crate</span>::Match&gt; {
<a href=#353 id=353 data-nosnippet>353</a> <span class="comment">// SAFETY: The Teddy implementations all require a minimum haystack
<a href=#354 id=354 data-nosnippet>354</a> // length, and this is required for safety. Therefore, we assert it
<a href=#355 id=355 data-nosnippet>355</a> // here in order to make this method sound.
<a href=#356 id=356 data-nosnippet>356</a> </span><span class="macro">assert!</span>(haystack[at..].len() &gt;= <span class="self">self</span>.minimum_len);
<a href=#357 id=357 data-nosnippet>357</a> <span class="kw">let </span>hayptr = haystack.as_ptr();
<a href=#358 id=358 data-nosnippet>358</a> <span class="comment">// SAFETY: Construction of the searcher guarantees that we are able
<a href=#359 id=359 data-nosnippet>359</a> // to run it in the current environment (i.e., we won't get an AVX2
<a href=#360 id=360 data-nosnippet>360</a> // searcher on a x86-64 CPU without AVX2 support). Also, the pointers
<a href=#361 id=361 data-nosnippet>361</a> // are valid as they are derived directly from a borrowed slice.
<a href=#362 id=362 data-nosnippet>362</a> </span><span class="kw">let </span>teddym = <span class="kw">unsafe </span>{
<a href=#363 id=363 data-nosnippet>363</a> <span class="self">self</span>.imp.find(hayptr.add(at), hayptr.add(haystack.len()))<span class="question-mark">?
<a href=#364 id=364 data-nosnippet>364</a> </span>};
<a href=#365 id=365 data-nosnippet>365</a> <span class="kw">let </span>start = teddym.start().as_usize().wrapping_sub(hayptr.as_usize());
<a href=#366 id=366 data-nosnippet>366</a> <span class="kw">let </span>end = teddym.end().as_usize().wrapping_sub(hayptr.as_usize());
<a href=#367 id=367 data-nosnippet>367</a> <span class="kw">let </span>span = <span class="kw">crate</span>::Span { start, end };
<a href=#368 id=368 data-nosnippet>368</a> <span class="comment">// OK because we won't permit the construction of a searcher that
<a href=#369 id=369 data-nosnippet>369</a> // could report a pattern ID bigger than what can fit in the crate-wide
<a href=#370 id=370 data-nosnippet>370</a> // PatternID type.
<a href=#371 id=371 data-nosnippet>371</a> </span><span class="kw">let </span>pid = <span class="kw">crate</span>::PatternID::new_unchecked(teddym.pattern().as_usize());
<a href=#372 id=372 data-nosnippet>372</a> <span class="kw">let </span>m = <span class="kw">crate</span>::Match::new(pid, span);
<a href=#373 id=373 data-nosnippet>373</a> <span class="prelude-val">Some</span>(m)
<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> <span class="doccomment">/// Returns the approximate total amount of heap used by this type, in
<a href=#377 id=377 data-nosnippet>377</a> /// units of bytes.
<a href=#378 id=378 data-nosnippet>378</a> </span><span class="attr">#[inline(always)]
<a href=#379 id=379 data-nosnippet>379</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=#380 id=380 data-nosnippet>380</a> <span class="self">self</span>.memory_usage
<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> <span class="doccomment">/// Returns the minimum length, in bytes, that a haystack must be in order
<a href=#384 id=384 data-nosnippet>384</a> /// to use it with this searcher.
<a href=#385 id=385 data-nosnippet>385</a> </span><span class="attr">#[inline(always)]
<a href=#386 id=386 data-nosnippet>386</a> </span><span class="kw">pub</span>(<span class="kw">crate</span>) <span class="kw">fn </span>minimum_len(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; usize {
<a href=#387 id=387 data-nosnippet>387</a> <span class="self">self</span>.minimum_len
<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>
<a href=#391 id=391 data-nosnippet>391</a><span class="doccomment">/// A trait that provides dynamic dispatch over the different possible Teddy
<a href=#392 id=392 data-nosnippet>392</a>/// variants on the same algorithm.
<a href=#393 id=393 data-nosnippet>393</a>///
<a href=#394 id=394 data-nosnippet>394</a>/// On `x86_64` for example, it isn't known until runtime which of 12 possible
<a href=#395 id=395 data-nosnippet>395</a>/// variants will be used. One might use one of the four slim 128-bit vector
<a href=#396 id=396 data-nosnippet>396</a>/// variants, or one of the four 256-bit vector variants or even one of the
<a href=#397 id=397 data-nosnippet>397</a>/// four fat 256-bit vector variants.
<a href=#398 id=398 data-nosnippet>398</a>///
<a href=#399 id=399 data-nosnippet>399</a>/// Since this choice is generally made when the Teddy searcher is constructed
<a href=#400 id=400 data-nosnippet>400</a>/// and this choice is based on the patterns given and what the current CPU
<a href=#401 id=401 data-nosnippet>401</a>/// supports, it follows that there must be some kind of indirection at search
<a href=#402 id=402 data-nosnippet>402</a>/// time that "selects" the variant chosen at build time.
<a href=#403 id=403 data-nosnippet>403</a>///
<a href=#404 id=404 data-nosnippet>404</a>/// There are a few different ways to go about this. One approach is to use an
<a href=#405 id=405 data-nosnippet>405</a>/// enum. It works fine, but in my experiments, this generally results in worse
<a href=#406 id=406 data-nosnippet>406</a>/// codegen. Another approach, which is what we use here, is dynamic dispatch
<a href=#407 id=407 data-nosnippet>407</a>/// via a trait object. We basically implement this trait for each possible
<a href=#408 id=408 data-nosnippet>408</a>/// variant, select the variant we want at build time and convert it to a
<a href=#409 id=409 data-nosnippet>409</a>/// trait object for use at search time.
<a href=#410 id=410 data-nosnippet>410</a>///
<a href=#411 id=411 data-nosnippet>411</a>/// Another approach is to use function pointers and stick each of the possible
<a href=#412 id=412 data-nosnippet>412</a>/// variants into a union. This is essentially isomorphic to the dynamic
<a href=#413 id=413 data-nosnippet>413</a>/// dispatch approach, but doesn't require any allocations. Since this crate
<a href=#414 id=414 data-nosnippet>414</a>/// requires `alloc`, there's no real reason (AFAIK) to go down this path. (The
<a href=#415 id=415 data-nosnippet>415</a>/// `memchr` crate does this.)
<a href=#416 id=416 data-nosnippet>416</a></span><span class="kw">trait </span>SearcherT:
<a href=#417 id=417 data-nosnippet>417</a> Debug + Send + Sync + UnwindSafe + RefUnwindSafe + <span class="lifetime">'static
<a href=#418 id=418 data-nosnippet>418</a></span>{
<a href=#419 id=419 data-nosnippet>419</a> <span class="doccomment">/// Execute a search on the given haystack (identified by `start` and `end`
<a href=#420 id=420 data-nosnippet>420</a> /// raw pointers).
<a href=#421 id=421 data-nosnippet>421</a> ///
<a href=#422 id=422 data-nosnippet>422</a> /// # Safety
<a href=#423 id=423 data-nosnippet>423</a> ///
<a href=#424 id=424 data-nosnippet>424</a> /// Essentially, the `start` and `end` pointers must be valid and point
<a href=#425 id=425 data-nosnippet>425</a> /// to a haystack one can read. As long as you derive them from, for
<a href=#426 id=426 data-nosnippet>426</a> /// example, a `&amp;[u8]`, they should automatically satisfy all of the safety
<a href=#427 id=427 data-nosnippet>427</a> /// obligations:
<a href=#428 id=428 data-nosnippet>428</a> ///
<a href=#429 id=429 data-nosnippet>429</a> /// * Both `start` and `end` must be valid for reads.
<a href=#430 id=430 data-nosnippet>430</a> /// * Both `start` and `end` must point to an initialized value.
<a href=#431 id=431 data-nosnippet>431</a> /// * Both `start` and `end` must point to the same allocated object and
<a href=#432 id=432 data-nosnippet>432</a> /// must either be in bounds or at most one byte past the end of the
<a href=#433 id=433 data-nosnippet>433</a> /// allocated object.
<a href=#434 id=434 data-nosnippet>434</a> /// * Both `start` and `end` must be _derived from_ a pointer to the same
<a href=#435 id=435 data-nosnippet>435</a> /// object.
<a href=#436 id=436 data-nosnippet>436</a> /// * The distance between `start` and `end` must not overflow `isize`.
<a href=#437 id=437 data-nosnippet>437</a> /// * The distance being in bounds must not rely on "wrapping around" the
<a href=#438 id=438 data-nosnippet>438</a> /// address space.
<a href=#439 id=439 data-nosnippet>439</a> /// * It must be the case that `start &lt;= end`.
<a href=#440 id=440 data-nosnippet>440</a> /// * `end - start` must be greater than the minimum length for this
<a href=#441 id=441 data-nosnippet>441</a> /// searcher.
<a href=#442 id=442 data-nosnippet>442</a> ///
<a href=#443 id=443 data-nosnippet>443</a> /// Also, it is expected that implementations of this trait will tag this
<a href=#444 id=444 data-nosnippet>444</a> /// method with a `target_feature` attribute. Callers must ensure that
<a href=#445 id=445 data-nosnippet>445</a> /// they are executing this method in an environment where that attribute
<a href=#446 id=446 data-nosnippet>446</a> /// is valid.
<a href=#447 id=447 data-nosnippet>447</a> </span><span class="kw">unsafe fn </span>find(<span class="kw-2">&amp;</span><span class="self">self</span>, start: <span class="kw-2">*const </span>u8, end: <span class="kw-2">*const </span>u8) -&gt; <span class="prelude-ty">Option</span>&lt;Match&gt;;
<a href=#448 id=448 data-nosnippet>448</a>}
<a href=#449 id=449 data-nosnippet>449</a>
<a href=#450 id=450 data-nosnippet>450</a><span class="attr">#[cfg(all(target_arch = <span class="string">"x86_64"</span>, target_feature = <span class="string">"sse2"</span>))]
<a href=#451 id=451 data-nosnippet>451</a></span><span class="kw">mod </span>x86_64 {
<a href=#452 id=452 data-nosnippet>452</a> <span class="kw">use </span>core::arch::x86_64::{__m128i, __m256i};
<a href=#453 id=453 data-nosnippet>453</a>
<a href=#454 id=454 data-nosnippet>454</a> <span class="kw">use </span>alloc::sync::Arc;
<a href=#455 id=455 data-nosnippet>455</a>
<a href=#456 id=456 data-nosnippet>456</a> <span class="kw">use </span><span class="kw">crate</span>::packed::{
<a href=#457 id=457 data-nosnippet>457</a> ext::Pointer,
<a href=#458 id=458 data-nosnippet>458</a> pattern::Patterns,
<a href=#459 id=459 data-nosnippet>459</a> teddy::generic::{<span class="self">self</span>, Match},
<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="kw">use super</span>::{Searcher, SearcherT};
<a href=#463 id=463 data-nosnippet>463</a>
<a href=#464 id=464 data-nosnippet>464</a> <span class="attr">#[derive(Clone, Debug)]
<a href=#465 id=465 data-nosnippet>465</a> </span><span class="kw">pub</span>(<span class="kw">super</span>) <span class="kw">struct </span>SlimSSSE3&lt;<span class="kw">const </span>BYTES: usize&gt; {
<a href=#466 id=466 data-nosnippet>466</a> slim128: generic::Slim&lt;__m128i, BYTES&gt;,
<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="comment">// Defines SlimSSSE3 wrapper functions for 1, 2, 3 and 4 bytes.
<a href=#470 id=470 data-nosnippet>470</a> </span><span class="macro">macro_rules!</span> slim_ssse3 {
<a href=#471 id=471 data-nosnippet>471</a> (<span class="macro-nonterminal">$len</span>:expr) =&gt; {
<a href=#472 id=472 data-nosnippet>472</a> <span class="kw">impl </span>SlimSSSE3&lt;<span class="macro-nonterminal">$len</span>&gt; {
<a href=#473 id=473 data-nosnippet>473</a> <span class="doccomment">/// Creates a new searcher using "slim" Teddy with 128-bit
<a href=#474 id=474 data-nosnippet>474</a> /// vectors. If SSSE3 is not available in the current
<a href=#475 id=475 data-nosnippet>475</a> /// environment, then this returns `None`.
<a href=#476 id=476 data-nosnippet>476</a> </span><span class="kw">pub</span>(<span class="kw">super</span>) <span class="kw">fn </span>new(
<a href=#477 id=477 data-nosnippet>477</a> patterns: <span class="kw-2">&amp;</span>Arc&lt;Patterns&gt;,
<a href=#478 id=478 data-nosnippet>478</a> ) -&gt; <span class="prelude-ty">Option</span>&lt;Searcher&gt; {
<a href=#479 id=479 data-nosnippet>479</a> <span class="kw">if </span>!is_available_ssse3() {
<a href=#480 id=480 data-nosnippet>480</a> <span class="kw">return </span><span class="prelude-val">None</span>;
<a href=#481 id=481 data-nosnippet>481</a> }
<a href=#482 id=482 data-nosnippet>482</a> <span class="prelude-val">Some</span>(<span class="kw">unsafe </span>{ SlimSSSE3::&lt;<span class="macro-nonterminal">$len</span>&gt;::new_unchecked(patterns) })
<a href=#483 id=483 data-nosnippet>483</a> }
<a href=#484 id=484 data-nosnippet>484</a>
<a href=#485 id=485 data-nosnippet>485</a> <span class="doccomment">/// Creates a new searcher using "slim" Teddy with 256-bit
<a href=#486 id=486 data-nosnippet>486</a> /// vectors without checking whether SSSE3 is available or not.
<a href=#487 id=487 data-nosnippet>487</a> ///
<a href=#488 id=488 data-nosnippet>488</a> /// # Safety
<a href=#489 id=489 data-nosnippet>489</a> ///
<a href=#490 id=490 data-nosnippet>490</a> /// Callers must ensure that SSSE3 is available in the current
<a href=#491 id=491 data-nosnippet>491</a> /// environment.
<a href=#492 id=492 data-nosnippet>492</a> </span><span class="attr">#[target_feature(enable = <span class="string">"ssse3"</span>)]
<a href=#493 id=493 data-nosnippet>493</a> </span><span class="kw">unsafe fn </span>new_unchecked(patterns: <span class="kw-2">&amp;</span>Arc&lt;Patterns&gt;) -&gt; Searcher {
<a href=#494 id=494 data-nosnippet>494</a> <span class="kw">let </span>slim128 = generic::Slim::&lt;__m128i, <span class="macro-nonterminal">$len</span>&gt;::new(
<a href=#495 id=495 data-nosnippet>495</a> Arc::clone(patterns),
<a href=#496 id=496 data-nosnippet>496</a> );
<a href=#497 id=497 data-nosnippet>497</a> <span class="kw">let </span>memory_usage = slim128.memory_usage();
<a href=#498 id=498 data-nosnippet>498</a> <span class="kw">let </span>minimum_len = slim128.minimum_len();
<a href=#499 id=499 data-nosnippet>499</a> <span class="kw">let </span>imp = Arc::new(SlimSSSE3 { slim128 });
<a href=#500 id=500 data-nosnippet>500</a> Searcher { imp, memory_usage, minimum_len }
<a href=#501 id=501 data-nosnippet>501</a> }
<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> <span class="kw">impl </span>SearcherT <span class="kw">for </span>SlimSSSE3&lt;<span class="macro-nonterminal">$len</span>&gt; {
<a href=#505 id=505 data-nosnippet>505</a> <span class="attr">#[target_feature(enable = <span class="string">"ssse3"</span>)]
<a href=#506 id=506 data-nosnippet>506</a> #[inline]
<a href=#507 id=507 data-nosnippet>507</a> </span><span class="kw">unsafe fn </span>find(
<a href=#508 id=508 data-nosnippet>508</a> <span class="kw-2">&amp;</span><span class="self">self</span>,
<a href=#509 id=509 data-nosnippet>509</a> start: <span class="kw-2">*const </span>u8,
<a href=#510 id=510 data-nosnippet>510</a> end: <span class="kw-2">*const </span>u8,
<a href=#511 id=511 data-nosnippet>511</a> ) -&gt; <span class="prelude-ty">Option</span>&lt;Match&gt; {
<a href=#512 id=512 data-nosnippet>512</a> <span class="comment">// SAFETY: All obligations except for `target_feature` are
<a href=#513 id=513 data-nosnippet>513</a> // passed to the caller. Our use of `target_feature` is
<a href=#514 id=514 data-nosnippet>514</a> // safe because construction of this type requires that the
<a href=#515 id=515 data-nosnippet>515</a> // requisite target features are available.
<a href=#516 id=516 data-nosnippet>516</a> </span><span class="self">self</span>.slim128.find(start, end)
<a href=#517 id=517 data-nosnippet>517</a> }
<a href=#518 id=518 data-nosnippet>518</a> }
<a href=#519 id=519 data-nosnippet>519</a> };
<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> <span class="macro">slim_ssse3!</span>(<span class="number">1</span>);
<a href=#523 id=523 data-nosnippet>523</a> <span class="macro">slim_ssse3!</span>(<span class="number">2</span>);
<a href=#524 id=524 data-nosnippet>524</a> <span class="macro">slim_ssse3!</span>(<span class="number">3</span>);
<a href=#525 id=525 data-nosnippet>525</a> <span class="macro">slim_ssse3!</span>(<span class="number">4</span>);
<a href=#526 id=526 data-nosnippet>526</a>
<a href=#527 id=527 data-nosnippet>527</a> <span class="attr">#[derive(Clone, Debug)]
<a href=#528 id=528 data-nosnippet>528</a> </span><span class="kw">pub</span>(<span class="kw">super</span>) <span class="kw">struct </span>SlimAVX2&lt;<span class="kw">const </span>BYTES: usize&gt; {
<a href=#529 id=529 data-nosnippet>529</a> slim128: generic::Slim&lt;__m128i, BYTES&gt;,
<a href=#530 id=530 data-nosnippet>530</a> slim256: generic::Slim&lt;__m256i, BYTES&gt;,
<a href=#531 id=531 data-nosnippet>531</a> }
<a href=#532 id=532 data-nosnippet>532</a>
<a href=#533 id=533 data-nosnippet>533</a> <span class="comment">// Defines SlimAVX2 wrapper functions for 1, 2, 3 and 4 bytes.
<a href=#534 id=534 data-nosnippet>534</a> </span><span class="macro">macro_rules!</span> slim_avx2 {
<a href=#535 id=535 data-nosnippet>535</a> (<span class="macro-nonterminal">$len</span>:expr) =&gt; {
<a href=#536 id=536 data-nosnippet>536</a> <span class="kw">impl </span>SlimAVX2&lt;<span class="macro-nonterminal">$len</span>&gt; {
<a href=#537 id=537 data-nosnippet>537</a> <span class="doccomment">/// Creates a new searcher using "slim" Teddy with 256-bit
<a href=#538 id=538 data-nosnippet>538</a> /// vectors. If AVX2 is not available in the current
<a href=#539 id=539 data-nosnippet>539</a> /// environment, then this returns `None`.
<a href=#540 id=540 data-nosnippet>540</a> </span><span class="kw">pub</span>(<span class="kw">super</span>) <span class="kw">fn </span>new(
<a href=#541 id=541 data-nosnippet>541</a> patterns: <span class="kw-2">&amp;</span>Arc&lt;Patterns&gt;,
<a href=#542 id=542 data-nosnippet>542</a> ) -&gt; <span class="prelude-ty">Option</span>&lt;Searcher&gt; {
<a href=#543 id=543 data-nosnippet>543</a> <span class="kw">if </span>!is_available_avx2() {
<a href=#544 id=544 data-nosnippet>544</a> <span class="kw">return </span><span class="prelude-val">None</span>;
<a href=#545 id=545 data-nosnippet>545</a> }
<a href=#546 id=546 data-nosnippet>546</a> <span class="prelude-val">Some</span>(<span class="kw">unsafe </span>{ SlimAVX2::&lt;<span class="macro-nonterminal">$len</span>&gt;::new_unchecked(patterns) })
<a href=#547 id=547 data-nosnippet>547</a> }
<a href=#548 id=548 data-nosnippet>548</a>
<a href=#549 id=549 data-nosnippet>549</a> <span class="doccomment">/// Creates a new searcher using "slim" Teddy with 256-bit
<a href=#550 id=550 data-nosnippet>550</a> /// vectors without checking whether AVX2 is available or not.
<a href=#551 id=551 data-nosnippet>551</a> ///
<a href=#552 id=552 data-nosnippet>552</a> /// # Safety
<a href=#553 id=553 data-nosnippet>553</a> ///
<a href=#554 id=554 data-nosnippet>554</a> /// Callers must ensure that AVX2 is available in the current
<a href=#555 id=555 data-nosnippet>555</a> /// environment.
<a href=#556 id=556 data-nosnippet>556</a> </span><span class="attr">#[target_feature(enable = <span class="string">"avx2"</span>)]
<a href=#557 id=557 data-nosnippet>557</a> </span><span class="kw">unsafe fn </span>new_unchecked(patterns: <span class="kw-2">&amp;</span>Arc&lt;Patterns&gt;) -&gt; Searcher {
<a href=#558 id=558 data-nosnippet>558</a> <span class="kw">let </span>slim128 = generic::Slim::&lt;__m128i, <span class="macro-nonterminal">$len</span>&gt;::new(
<a href=#559 id=559 data-nosnippet>559</a> Arc::clone(<span class="kw-2">&amp;</span>patterns),
<a href=#560 id=560 data-nosnippet>560</a> );
<a href=#561 id=561 data-nosnippet>561</a> <span class="kw">let </span>slim256 = generic::Slim::&lt;__m256i, <span class="macro-nonterminal">$len</span>&gt;::new(
<a href=#562 id=562 data-nosnippet>562</a> Arc::clone(<span class="kw-2">&amp;</span>patterns),
<a href=#563 id=563 data-nosnippet>563</a> );
<a href=#564 id=564 data-nosnippet>564</a> <span class="kw">let </span>memory_usage =
<a href=#565 id=565 data-nosnippet>565</a> slim128.memory_usage() + slim256.memory_usage();
<a href=#566 id=566 data-nosnippet>566</a> <span class="kw">let </span>minimum_len = slim128.minimum_len();
<a href=#567 id=567 data-nosnippet>567</a> <span class="kw">let </span>imp = Arc::new(SlimAVX2 { slim128, slim256 });
<a href=#568 id=568 data-nosnippet>568</a> Searcher { imp, memory_usage, minimum_len }
<a href=#569 id=569 data-nosnippet>569</a> }
<a href=#570 id=570 data-nosnippet>570</a> }
<a href=#571 id=571 data-nosnippet>571</a>
<a href=#572 id=572 data-nosnippet>572</a> <span class="kw">impl </span>SearcherT <span class="kw">for </span>SlimAVX2&lt;<span class="macro-nonterminal">$len</span>&gt; {
<a href=#573 id=573 data-nosnippet>573</a> <span class="attr">#[target_feature(enable = <span class="string">"avx2"</span>)]
<a href=#574 id=574 data-nosnippet>574</a> #[inline]
<a href=#575 id=575 data-nosnippet>575</a> </span><span class="kw">unsafe fn </span>find(
<a href=#576 id=576 data-nosnippet>576</a> <span class="kw-2">&amp;</span><span class="self">self</span>,
<a href=#577 id=577 data-nosnippet>577</a> start: <span class="kw-2">*const </span>u8,
<a href=#578 id=578 data-nosnippet>578</a> end: <span class="kw-2">*const </span>u8,
<a href=#579 id=579 data-nosnippet>579</a> ) -&gt; <span class="prelude-ty">Option</span>&lt;Match&gt; {
<a href=#580 id=580 data-nosnippet>580</a> <span class="comment">// SAFETY: All obligations except for `target_feature` are
<a href=#581 id=581 data-nosnippet>581</a> // passed to the caller. Our use of `target_feature` is
<a href=#582 id=582 data-nosnippet>582</a> // safe because construction of this type requires that the
<a href=#583 id=583 data-nosnippet>583</a> // requisite target features are available.
<a href=#584 id=584 data-nosnippet>584</a> </span><span class="kw">let </span>len = end.distance(start);
<a href=#585 id=585 data-nosnippet>585</a> <span class="kw">if </span>len &lt; <span class="self">self</span>.slim256.minimum_len() {
<a href=#586 id=586 data-nosnippet>586</a> <span class="self">self</span>.slim128.find(start, end)
<a href=#587 id=587 data-nosnippet>587</a> } <span class="kw">else </span>{
<a href=#588 id=588 data-nosnippet>588</a> <span class="self">self</span>.slim256.find(start, end)
<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> }
<a href=#592 id=592 data-nosnippet>592</a> };
<a href=#593 id=593 data-nosnippet>593</a> }
<a href=#594 id=594 data-nosnippet>594</a>
<a href=#595 id=595 data-nosnippet>595</a> <span class="macro">slim_avx2!</span>(<span class="number">1</span>);
<a href=#596 id=596 data-nosnippet>596</a> <span class="macro">slim_avx2!</span>(<span class="number">2</span>);
<a href=#597 id=597 data-nosnippet>597</a> <span class="macro">slim_avx2!</span>(<span class="number">3</span>);
<a href=#598 id=598 data-nosnippet>598</a> <span class="macro">slim_avx2!</span>(<span class="number">4</span>);
<a href=#599 id=599 data-nosnippet>599</a>
<a href=#600 id=600 data-nosnippet>600</a> <span class="attr">#[derive(Clone, Debug)]
<a href=#601 id=601 data-nosnippet>601</a> </span><span class="kw">pub</span>(<span class="kw">super</span>) <span class="kw">struct </span>FatAVX2&lt;<span class="kw">const </span>BYTES: usize&gt; {
<a href=#602 id=602 data-nosnippet>602</a> fat256: generic::Fat&lt;__m256i, BYTES&gt;,
<a href=#603 id=603 data-nosnippet>603</a> }
<a href=#604 id=604 data-nosnippet>604</a>
<a href=#605 id=605 data-nosnippet>605</a> <span class="comment">// Defines SlimAVX2 wrapper functions for 1, 2, 3 and 4 bytes.
<a href=#606 id=606 data-nosnippet>606</a> </span><span class="macro">macro_rules!</span> fat_avx2 {
<a href=#607 id=607 data-nosnippet>607</a> (<span class="macro-nonterminal">$len</span>:expr) =&gt; {
<a href=#608 id=608 data-nosnippet>608</a> <span class="kw">impl </span>FatAVX2&lt;<span class="macro-nonterminal">$len</span>&gt; {
<a href=#609 id=609 data-nosnippet>609</a> <span class="doccomment">/// Creates a new searcher using "slim" Teddy with 256-bit
<a href=#610 id=610 data-nosnippet>610</a> /// vectors. If AVX2 is not available in the current
<a href=#611 id=611 data-nosnippet>611</a> /// environment, then this returns `None`.
<a href=#612 id=612 data-nosnippet>612</a> </span><span class="kw">pub</span>(<span class="kw">super</span>) <span class="kw">fn </span>new(
<a href=#613 id=613 data-nosnippet>613</a> patterns: <span class="kw-2">&amp;</span>Arc&lt;Patterns&gt;,
<a href=#614 id=614 data-nosnippet>614</a> ) -&gt; <span class="prelude-ty">Option</span>&lt;Searcher&gt; {
<a href=#615 id=615 data-nosnippet>615</a> <span class="kw">if </span>!is_available_avx2() {
<a href=#616 id=616 data-nosnippet>616</a> <span class="kw">return </span><span class="prelude-val">None</span>;
<a href=#617 id=617 data-nosnippet>617</a> }
<a href=#618 id=618 data-nosnippet>618</a> <span class="prelude-val">Some</span>(<span class="kw">unsafe </span>{ FatAVX2::&lt;<span class="macro-nonterminal">$len</span>&gt;::new_unchecked(patterns) })
<a href=#619 id=619 data-nosnippet>619</a> }
<a href=#620 id=620 data-nosnippet>620</a>
<a href=#621 id=621 data-nosnippet>621</a> <span class="doccomment">/// Creates a new searcher using "slim" Teddy with 256-bit
<a href=#622 id=622 data-nosnippet>622</a> /// vectors without checking whether AVX2 is available or not.
<a href=#623 id=623 data-nosnippet>623</a> ///
<a href=#624 id=624 data-nosnippet>624</a> /// # Safety
<a href=#625 id=625 data-nosnippet>625</a> ///
<a href=#626 id=626 data-nosnippet>626</a> /// Callers must ensure that AVX2 is available in the current
<a href=#627 id=627 data-nosnippet>627</a> /// environment.
<a href=#628 id=628 data-nosnippet>628</a> </span><span class="attr">#[target_feature(enable = <span class="string">"avx2"</span>)]
<a href=#629 id=629 data-nosnippet>629</a> </span><span class="kw">unsafe fn </span>new_unchecked(patterns: <span class="kw-2">&amp;</span>Arc&lt;Patterns&gt;) -&gt; Searcher {
<a href=#630 id=630 data-nosnippet>630</a> <span class="kw">let </span>fat256 = generic::Fat::&lt;__m256i, <span class="macro-nonterminal">$len</span>&gt;::new(
<a href=#631 id=631 data-nosnippet>631</a> Arc::clone(<span class="kw-2">&amp;</span>patterns),
<a href=#632 id=632 data-nosnippet>632</a> );
<a href=#633 id=633 data-nosnippet>633</a> <span class="kw">let </span>memory_usage = fat256.memory_usage();
<a href=#634 id=634 data-nosnippet>634</a> <span class="kw">let </span>minimum_len = fat256.minimum_len();
<a href=#635 id=635 data-nosnippet>635</a> <span class="kw">let </span>imp = Arc::new(FatAVX2 { fat256 });
<a href=#636 id=636 data-nosnippet>636</a> Searcher { imp, memory_usage, minimum_len }
<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">impl </span>SearcherT <span class="kw">for </span>FatAVX2&lt;<span class="macro-nonterminal">$len</span>&gt; {
<a href=#641 id=641 data-nosnippet>641</a> <span class="attr">#[target_feature(enable = <span class="string">"avx2"</span>)]
<a href=#642 id=642 data-nosnippet>642</a> #[inline]
<a href=#643 id=643 data-nosnippet>643</a> </span><span class="kw">unsafe fn </span>find(
<a href=#644 id=644 data-nosnippet>644</a> <span class="kw-2">&amp;</span><span class="self">self</span>,
<a href=#645 id=645 data-nosnippet>645</a> start: <span class="kw-2">*const </span>u8,
<a href=#646 id=646 data-nosnippet>646</a> end: <span class="kw-2">*const </span>u8,
<a href=#647 id=647 data-nosnippet>647</a> ) -&gt; <span class="prelude-ty">Option</span>&lt;Match&gt; {
<a href=#648 id=648 data-nosnippet>648</a> <span class="comment">// SAFETY: All obligations except for `target_feature` are
<a href=#649 id=649 data-nosnippet>649</a> // passed to the caller. Our use of `target_feature` is
<a href=#650 id=650 data-nosnippet>650</a> // safe because construction of this type requires that the
<a href=#651 id=651 data-nosnippet>651</a> // requisite target features are available.
<a href=#652 id=652 data-nosnippet>652</a> </span><span class="self">self</span>.fat256.find(start, end)
<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> }
<a href=#657 id=657 data-nosnippet>657</a>
<a href=#658 id=658 data-nosnippet>658</a> <span class="macro">fat_avx2!</span>(<span class="number">1</span>);
<a href=#659 id=659 data-nosnippet>659</a> <span class="macro">fat_avx2!</span>(<span class="number">2</span>);
<a href=#660 id=660 data-nosnippet>660</a> <span class="macro">fat_avx2!</span>(<span class="number">3</span>);
<a href=#661 id=661 data-nosnippet>661</a> <span class="macro">fat_avx2!</span>(<span class="number">4</span>);
<a href=#662 id=662 data-nosnippet>662</a>
<a href=#663 id=663 data-nosnippet>663</a> <span class="attr">#[inline]
<a href=#664 id=664 data-nosnippet>664</a> </span><span class="kw">pub</span>(<span class="kw">super</span>) <span class="kw">fn </span>is_available_ssse3() -&gt; bool {
<a href=#665 id=665 data-nosnippet>665</a> <span class="attr">#[cfg(not(target_feature = <span class="string">"sse2"</span>))]
<a href=#666 id=666 data-nosnippet>666</a> </span>{
<a href=#667 id=667 data-nosnippet>667</a> <span class="bool-val">false
<a href=#668 id=668 data-nosnippet>668</a> </span>}
<a href=#669 id=669 data-nosnippet>669</a> <span class="attr">#[cfg(target_feature = <span class="string">"sse2"</span>)]
<a href=#670 id=670 data-nosnippet>670</a> </span>{
<a href=#671 id=671 data-nosnippet>671</a> <span class="attr">#[cfg(target_feature = <span class="string">"ssse3"</span>)]
<a href=#672 id=672 data-nosnippet>672</a> </span>{
<a href=#673 id=673 data-nosnippet>673</a> <span class="bool-val">true
<a href=#674 id=674 data-nosnippet>674</a> </span>}
<a href=#675 id=675 data-nosnippet>675</a> <span class="attr">#[cfg(not(target_feature = <span class="string">"ssse3"</span>))]
<a href=#676 id=676 data-nosnippet>676</a> </span>{
<a href=#677 id=677 data-nosnippet>677</a> <span class="attr">#[cfg(feature = <span class="string">"std"</span>)]
<a href=#678 id=678 data-nosnippet>678</a> </span>{
<a href=#679 id=679 data-nosnippet>679</a> <span class="macro">std::is_x86_feature_detected!</span>(<span class="string">"ssse3"</span>)
<a href=#680 id=680 data-nosnippet>680</a> }
<a href=#681 id=681 data-nosnippet>681</a> <span class="attr">#[cfg(not(feature = <span class="string">"std"</span>))]
<a href=#682 id=682 data-nosnippet>682</a> </span>{
<a href=#683 id=683 data-nosnippet>683</a> <span class="bool-val">false
<a href=#684 id=684 data-nosnippet>684</a> </span>}
<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>
<a href=#689 id=689 data-nosnippet>689</a> <span class="attr">#[inline]
<a href=#690 id=690 data-nosnippet>690</a> </span><span class="kw">pub</span>(<span class="kw">super</span>) <span class="kw">fn </span>is_available_avx2() -&gt; bool {
<a href=#691 id=691 data-nosnippet>691</a> <span class="attr">#[cfg(not(target_feature = <span class="string">"sse2"</span>))]
<a href=#692 id=692 data-nosnippet>692</a> </span>{
<a href=#693 id=693 data-nosnippet>693</a> <span class="bool-val">false
<a href=#694 id=694 data-nosnippet>694</a> </span>}
<a href=#695 id=695 data-nosnippet>695</a> <span class="attr">#[cfg(target_feature = <span class="string">"sse2"</span>)]
<a href=#696 id=696 data-nosnippet>696</a> </span>{
<a href=#697 id=697 data-nosnippet>697</a> <span class="attr">#[cfg(target_feature = <span class="string">"avx2"</span>)]
<a href=#698 id=698 data-nosnippet>698</a> </span>{
<a href=#699 id=699 data-nosnippet>699</a> <span class="bool-val">true
<a href=#700 id=700 data-nosnippet>700</a> </span>}
<a href=#701 id=701 data-nosnippet>701</a> <span class="attr">#[cfg(not(target_feature = <span class="string">"avx2"</span>))]
<a href=#702 id=702 data-nosnippet>702</a> </span>{
<a href=#703 id=703 data-nosnippet>703</a> <span class="attr">#[cfg(feature = <span class="string">"std"</span>)]
<a href=#704 id=704 data-nosnippet>704</a> </span>{
<a href=#705 id=705 data-nosnippet>705</a> <span class="macro">std::is_x86_feature_detected!</span>(<span class="string">"avx2"</span>)
<a href=#706 id=706 data-nosnippet>706</a> }
<a href=#707 id=707 data-nosnippet>707</a> <span class="attr">#[cfg(not(feature = <span class="string">"std"</span>))]
<a href=#708 id=708 data-nosnippet>708</a> </span>{
<a href=#709 id=709 data-nosnippet>709</a> <span class="bool-val">false
<a href=#710 id=710 data-nosnippet>710</a> </span>}
<a href=#711 id=711 data-nosnippet>711</a> }
<a href=#712 id=712 data-nosnippet>712</a> }
<a href=#713 id=713 data-nosnippet>713</a> }
<a href=#714 id=714 data-nosnippet>714</a>}
<a href=#715 id=715 data-nosnippet>715</a>
<a href=#716 id=716 data-nosnippet>716</a><span class="attr">#[cfg(all(
<a href=#717 id=717 data-nosnippet>717</a> target_arch = <span class="string">"aarch64"</span>,
<a href=#718 id=718 data-nosnippet>718</a> target_feature = <span class="string">"neon"</span>,
<a href=#719 id=719 data-nosnippet>719</a> target_endian = <span class="string">"little"
<a href=#720 id=720 data-nosnippet>720</a></span>))]
<a href=#721 id=721 data-nosnippet>721</a></span><span class="kw">mod </span>aarch64 {
<a href=#722 id=722 data-nosnippet>722</a> <span class="kw">use </span>core::arch::aarch64::uint8x16_t;
<a href=#723 id=723 data-nosnippet>723</a>
<a href=#724 id=724 data-nosnippet>724</a> <span class="kw">use </span>alloc::sync::Arc;
<a href=#725 id=725 data-nosnippet>725</a>
<a href=#726 id=726 data-nosnippet>726</a> <span class="kw">use </span><span class="kw">crate</span>::packed::{
<a href=#727 id=727 data-nosnippet>727</a> pattern::Patterns,
<a href=#728 id=728 data-nosnippet>728</a> teddy::generic::{<span class="self">self</span>, Match},
<a href=#729 id=729 data-nosnippet>729</a> };
<a href=#730 id=730 data-nosnippet>730</a>
<a href=#731 id=731 data-nosnippet>731</a> <span class="kw">use super</span>::{Searcher, SearcherT};
<a href=#732 id=732 data-nosnippet>732</a>
<a href=#733 id=733 data-nosnippet>733</a> <span class="attr">#[derive(Clone, Debug)]
<a href=#734 id=734 data-nosnippet>734</a> </span><span class="kw">pub</span>(<span class="kw">super</span>) <span class="kw">struct </span>SlimNeon&lt;<span class="kw">const </span>BYTES: usize&gt; {
<a href=#735 id=735 data-nosnippet>735</a> slim128: generic::Slim&lt;uint8x16_t, BYTES&gt;,
<a href=#736 id=736 data-nosnippet>736</a> }
<a href=#737 id=737 data-nosnippet>737</a>
<a href=#738 id=738 data-nosnippet>738</a> <span class="comment">// Defines SlimSSSE3 wrapper functions for 1, 2, 3 and 4 bytes.
<a href=#739 id=739 data-nosnippet>739</a> </span><span class="macro">macro_rules!</span> slim_neon {
<a href=#740 id=740 data-nosnippet>740</a> (<span class="macro-nonterminal">$len</span>:expr) =&gt; {
<a href=#741 id=741 data-nosnippet>741</a> <span class="kw">impl </span>SlimNeon&lt;<span class="macro-nonterminal">$len</span>&gt; {
<a href=#742 id=742 data-nosnippet>742</a> <span class="doccomment">/// Creates a new searcher using "slim" Teddy with 128-bit
<a href=#743 id=743 data-nosnippet>743</a> /// vectors. If SSSE3 is not available in the current
<a href=#744 id=744 data-nosnippet>744</a> /// environment, then this returns `None`.
<a href=#745 id=745 data-nosnippet>745</a> </span><span class="kw">pub</span>(<span class="kw">super</span>) <span class="kw">fn </span>new(
<a href=#746 id=746 data-nosnippet>746</a> patterns: <span class="kw-2">&amp;</span>Arc&lt;Patterns&gt;,
<a href=#747 id=747 data-nosnippet>747</a> ) -&gt; <span class="prelude-ty">Option</span>&lt;Searcher&gt; {
<a href=#748 id=748 data-nosnippet>748</a> <span class="prelude-val">Some</span>(<span class="kw">unsafe </span>{ SlimNeon::&lt;<span class="macro-nonterminal">$len</span>&gt;::new_unchecked(patterns) })
<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="doccomment">/// Creates a new searcher using "slim" Teddy with 256-bit
<a href=#752 id=752 data-nosnippet>752</a> /// vectors without checking whether SSSE3 is available or not.
<a href=#753 id=753 data-nosnippet>753</a> ///
<a href=#754 id=754 data-nosnippet>754</a> /// # Safety
<a href=#755 id=755 data-nosnippet>755</a> ///
<a href=#756 id=756 data-nosnippet>756</a> /// Callers must ensure that SSSE3 is available in the current
<a href=#757 id=757 data-nosnippet>757</a> /// environment.
<a href=#758 id=758 data-nosnippet>758</a> </span><span class="attr">#[target_feature(enable = <span class="string">"neon"</span>)]
<a href=#759 id=759 data-nosnippet>759</a> </span><span class="kw">unsafe fn </span>new_unchecked(patterns: <span class="kw-2">&amp;</span>Arc&lt;Patterns&gt;) -&gt; Searcher {
<a href=#760 id=760 data-nosnippet>760</a> <span class="kw">let </span>slim128 = generic::Slim::&lt;uint8x16_t, <span class="macro-nonterminal">$len</span>&gt;::new(
<a href=#761 id=761 data-nosnippet>761</a> Arc::clone(patterns),
<a href=#762 id=762 data-nosnippet>762</a> );
<a href=#763 id=763 data-nosnippet>763</a> <span class="kw">let </span>memory_usage = slim128.memory_usage();
<a href=#764 id=764 data-nosnippet>764</a> <span class="kw">let </span>minimum_len = slim128.minimum_len();
<a href=#765 id=765 data-nosnippet>765</a> <span class="kw">let </span>imp = Arc::new(SlimNeon { slim128 });
<a href=#766 id=766 data-nosnippet>766</a> Searcher { imp, memory_usage, minimum_len }
<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="kw">impl </span>SearcherT <span class="kw">for </span>SlimNeon&lt;<span class="macro-nonterminal">$len</span>&gt; {
<a href=#771 id=771 data-nosnippet>771</a> <span class="attr">#[target_feature(enable = <span class="string">"neon"</span>)]
<a href=#772 id=772 data-nosnippet>772</a> #[inline]
<a href=#773 id=773 data-nosnippet>773</a> </span><span class="kw">unsafe fn </span>find(
<a href=#774 id=774 data-nosnippet>774</a> <span class="kw-2">&amp;</span><span class="self">self</span>,
<a href=#775 id=775 data-nosnippet>775</a> start: <span class="kw-2">*const </span>u8,
<a href=#776 id=776 data-nosnippet>776</a> end: <span class="kw-2">*const </span>u8,
<a href=#777 id=777 data-nosnippet>777</a> ) -&gt; <span class="prelude-ty">Option</span>&lt;Match&gt; {
<a href=#778 id=778 data-nosnippet>778</a> <span class="comment">// SAFETY: All obligations except for `target_feature` are
<a href=#779 id=779 data-nosnippet>779</a> // passed to the caller. Our use of `target_feature` is
<a href=#780 id=780 data-nosnippet>780</a> // safe because construction of this type requires that the
<a href=#781 id=781 data-nosnippet>781</a> // requisite target features are available.
<a href=#782 id=782 data-nosnippet>782</a> </span><span class="self">self</span>.slim128.find(start, end)
<a href=#783 id=783 data-nosnippet>783</a> }
<a href=#784 id=784 data-nosnippet>784</a> }
<a href=#785 id=785 data-nosnippet>785</a> };
<a href=#786 id=786 data-nosnippet>786</a> }
<a href=#787 id=787 data-nosnippet>787</a>
<a href=#788 id=788 data-nosnippet>788</a> <span class="macro">slim_neon!</span>(<span class="number">1</span>);
<a href=#789 id=789 data-nosnippet>789</a> <span class="macro">slim_neon!</span>(<span class="number">2</span>);
<a href=#790 id=790 data-nosnippet>790</a> <span class="macro">slim_neon!</span>(<span class="number">3</span>);
<a href=#791 id=791 data-nosnippet>791</a> <span class="macro">slim_neon!</span>(<span class="number">4</span>);
<a href=#792 id=792 data-nosnippet>792</a>}
</code></pre></div></section></main></body></html>

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,10 @@
<!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/packed/teddy/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/packed/teddy/</div>mod.rs</h1><rustdoc-toolbar></rustdoc-toolbar></div><div class="example-wrap digits-1"><pre class="rust"><code><a href=#1 id=1 data-nosnippet>1</a><span class="comment">// Regrettable, but Teddy stuff just isn't used on all targets. And for some
<a href=#2 id=2 data-nosnippet>2</a>// targets, like aarch64, only "slim" Teddy is used and so "fat" Teddy gets a
<a href=#3 id=3 data-nosnippet>3</a>// bunch of dead-code warnings. Just not worth trying to squash them. Blech.
<a href=#4 id=4 data-nosnippet>4</a></span><span class="attr">#![allow(dead_code)]
<a href=#5 id=5 data-nosnippet>5</a>
<a href=#6 id=6 data-nosnippet>6</a></span><span class="kw">pub</span>(<span class="kw">crate</span>) <span class="kw">use </span><span class="self">self</span>::builder::{Builder, Searcher};
<a href=#7 id=7 data-nosnippet>7</a>
<a href=#8 id=8 data-nosnippet>8</a><span class="kw">mod </span>builder;
<a href=#9 id=9 data-nosnippet>9</a><span class="kw">mod </span>generic;
</code></pre></div></section></main></body></html>

File diff suppressed because it is too large Load Diff

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>