Coverage Report

Created: 2026-06-30 07:02

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/rust/registry/src/index.crates.io-1949cf8c6b5b557f/fst-0.4.7/src/raw/mod.rs
Line
Count
Source
1
/*!
2
Operations on raw finite state transducers.
3
4
This sub-module exposes the guts of a finite state transducer. Many parts of
5
it, such as construction and traversal, are mirrored in the `set` and `map`
6
sub-modules. Other parts of it, such as direct access to nodes and transitions
7
in the transducer, do not have any analog.
8
9
# Overview of types
10
11
`Fst` is a read only interface to pre-constructed finite state transducers.
12
`Node` is a read only interface to a single node in a transducer. `Builder` is
13
used to create new finite state transducers. (Once a transducer is created, it
14
can never be modified.) `Stream` is a stream of all inputs and outputs in a
15
transducer. `StreamBuilder` builds range queries. `OpBuilder` collects streams
16
and executes set operations like `union` or `intersection` on them with the
17
option of specifying a merge strategy for output values.
18
19
Most of the rest of the types are streams from set operations.
20
*/
21
use std::cmp;
22
use std::fmt;
23
24
use crate::automaton::{AlwaysMatch, Automaton};
25
use crate::bytes;
26
use crate::error::Result;
27
use crate::stream::{IntoStreamer, Streamer};
28
29
pub use crate::raw::build::Builder;
30
pub use crate::raw::error::Error;
31
pub use crate::raw::node::{Node, Transitions};
32
pub use crate::raw::ops::{
33
    Difference, IndexedValue, Intersection, OpBuilder, SymmetricDifference,
34
    Union,
35
};
36
37
mod build;
38
mod common_inputs;
39
mod counting_writer;
40
mod crc32;
41
mod crc32_table;
42
mod error;
43
mod node;
44
mod ops;
45
mod registry;
46
mod registry_minimal;
47
#[cfg(test)]
48
mod tests;
49
50
/// The API version of this crate.
51
///
52
/// This version number is written to every finite state transducer created by
53
/// this crate. When a finite state transducer is read, its version number is
54
/// checked against this value.
55
///
56
/// Currently, any version mismatch results in an error. Fixing this requires
57
/// regenerating the finite state transducer or switching to a version of this
58
/// crate that is compatible with the serialized transducer. This particular
59
/// behavior may be relaxed in future versions.
60
pub const VERSION: u64 = 3;
61
62
/// A sentinel value used to indicate an empty final state.
63
const EMPTY_ADDRESS: CompiledAddr = 0;
64
65
/// A sentinel value used to indicate an invalid state.
66
///
67
/// This is never the address of a node in a serialized transducer.
68
const NONE_ADDRESS: CompiledAddr = 1;
69
70
/// FstType is a convention used to indicate the type of the underlying
71
/// transducer.
72
///
73
/// This crate reserves the range 0-255 (inclusive) but currently leaves the
74
/// meaning of 0-255 unspecified.
75
pub type FstType = u64;
76
77
/// CompiledAddr is the type used to address nodes in a finite state
78
/// transducer.
79
///
80
/// It is most useful as a pointer to nodes. It can be used in the `Fst::node`
81
/// method to resolve the pointer.
82
pub type CompiledAddr = usize;
83
84
/// An acyclic deterministic finite state transducer.
85
///
86
/// # How does it work?
87
///
88
/// The short answer: it's just like a prefix trie, which compresses keys
89
/// based only on their prefixes, except that a automaton/transducer also
90
/// compresses suffixes.
91
///
92
/// The longer answer is that keys in an automaton are stored only in the
93
/// transitions from one state to another. A key can be acquired by tracing
94
/// a path from the root of the automaton to any match state. The inputs along
95
/// each transition are concatenated. Once a match state is reached, the
96
/// concatenation of inputs up until that point corresponds to a single key.
97
///
98
/// But why is it called a transducer instead of an automaton? A finite state
99
/// transducer is just like a finite state automaton, except that it has output
100
/// transitions in addition to input transitions. Namely, the value associated
101
/// with any particular key is determined by summing the outputs along every
102
/// input transition that leads to the key's corresponding match state.
103
///
104
/// This is best demonstrated with a couple images. First, let's ignore the
105
/// "transducer" aspect and focus on a plain automaton.
106
///
107
/// Consider that your keys are abbreviations of some of the months in the
108
/// Gregorian calendar:
109
///
110
/// ```plain
111
/// jan
112
/// feb
113
/// mar
114
/// may
115
/// jun
116
/// jul
117
/// ```
118
///
119
/// The corresponding automaton that stores all of these as keys looks like
120
/// this:
121
///
122
/// ![finite state automaton](https://burntsushi.net/stuff/months-set.png)
123
///
124
/// Notice here how the prefix and suffix of `jan` and `jun` are shared.
125
/// Similarly, the prefixes of `jun` and `jul` are shared and the prefixes
126
/// of `mar` and `may` are shared.
127
///
128
/// All of the keys from this automaton can be enumerated in lexicographic
129
/// order by following every transition from each node in lexicographic
130
/// order. Since it is acyclic, the procedure will terminate.
131
///
132
/// A key can be found by tracing it through the transitions in the automaton.
133
/// For example, the key `aug` is known not to be in the automaton by only
134
/// visiting the root state (because there is no `a` transition). For another
135
/// example, the key `jax` is known not to be in the set only after moving
136
/// through the transitions for `j` and `a`. Namely, after those transitions
137
/// are followed, there are no transitions for `x`.
138
///
139
/// Notice here that looking up a key is proportional the length of the key
140
/// itself. Namely, lookup time is not affected by the number of keys in the
141
/// automaton!
142
///
143
/// Additionally, notice that the automaton exploits the fact that many keys
144
/// share common prefixes and suffixes. For example, `jun` and `jul` are
145
/// represented with no more states than would be required to represent either
146
/// one on its own. Instead, the only change is a single extra transition. This
147
/// is a form of compression and is key to how the automatons produced by this
148
/// crate are so small.
149
///
150
/// Let's move on to finite state transducers. Consider the same set of keys
151
/// as above, but let's assign their numeric month values:
152
///
153
/// ```plain
154
/// jan,1
155
/// feb,2
156
/// mar,3
157
/// may,5
158
/// jun,6
159
/// jul,7
160
/// ```
161
///
162
/// The corresponding transducer looks very similar to the automaton above,
163
/// except outputs have been added to some of the transitions:
164
///
165
/// ![finite state transducer](https://burntsushi.net/stuff/months-map.png)
166
///
167
/// All of the operations with a transducer are the same as described above
168
/// for automatons. Additionally, the same compression techniques are used:
169
/// common prefixes and suffixes in keys are exploited.
170
///
171
/// The key difference is that some transitions have been given an output.
172
/// As one follows input transitions, one must sum the outputs as they
173
/// are seen. (A transition with no output represents the additive identity,
174
/// or `0` in this case.) For example, when looking up `feb`, the transition
175
/// `f` has output `2`, the transition `e` has output `0`, and the transition
176
/// `b` also has output `0`. The sum of these is `2`, which is exactly the
177
/// value we associated with `feb`.
178
///
179
/// For another more interesting example, consider `jul`. The `j` transition
180
/// has output `1`, the `u` transition has output `5` and the `l` transition
181
/// has output `1`. Summing these together gets us `7`, which is again the
182
/// correct value associated with `jul`. Notice that if we instead looked up
183
/// the `jun` key, then the `n` transition would be followed instead of the
184
/// `l` transition, which has no output. Therefore, the `jun` key equals
185
/// `1+5+0=6`.
186
///
187
/// The trick to transducers is that there exists a unique path through the
188
/// transducer for every key, and its outputs are stored appropriately along
189
/// this path such that the correct value is returned when they are all summed
190
/// together. This process also enables the data that makes up each value to be
191
/// shared across many values in the transducer in exactly the same way that
192
/// keys are shared. This is yet another form of compression!
193
///
194
/// # Bonus: a billion strings
195
///
196
/// The amount of compression one can get from automata can be absolutely
197
/// ridiuclous. Consider the particular case of storing all billion strings
198
/// in the range `0000000001-1000000000`, e.g.,
199
///
200
/// ```plain
201
/// 0000000001
202
/// 0000000002
203
/// ...
204
/// 0000000100
205
/// 0000000101
206
/// ...
207
/// 0999999999
208
/// 1000000000
209
/// ```
210
///
211
/// The corresponding automaton looks like this:
212
///
213
/// ![finite state automaton - one billion strings](https://burntsushi.net/stuff/one-billion.png)
214
///
215
/// Indeed, the on disk size of this automaton is a mere **251 bytes**.
216
///
217
/// Of course, this is a bit of a pathological best case, but it does serve
218
/// to show how good compression can be in the optimal case.
219
///
220
/// Also, check out the
221
/// [corresponding transducer](https://burntsushi.net/stuff/one-billion-map.svg)
222
/// that maps each string to its integer value. It's a bit bigger, but still
223
/// only takes up **896 bytes** of space on disk. This demonstrates that
224
/// output values are also compressible.
225
///
226
/// # Does this crate produce minimal transducers?
227
///
228
/// For any non-trivial sized set of keys, it is unlikely that this crate will
229
/// produce a minimal transducer. As far as this author knows, guaranteeing a
230
/// minimal transducer requires working memory proportional to the number of
231
/// states. This can be quite costly and is anathema to the main design goal of
232
/// this crate: provide the ability to work with gigantic sets of strings with
233
/// constant memory overhead.
234
///
235
/// Instead, construction of a finite state transducer uses a cache of
236
/// states. More frequently used states are cached and reused, which provides
237
/// reasonably good compression ratios. (No comprehensive benchmarks exist to
238
/// back up this claim.)
239
///
240
/// It is possible that this crate may expose a way to guarantee minimal
241
/// construction of transducers at the expense of exorbitant memory
242
/// requirements.
243
///
244
/// # Bibliography
245
///
246
/// I initially got the idea to use finite state tranducers to represent
247
/// ordered sets/maps from
248
/// [Michael
249
/// McCandless'](http://blog.mikemccandless.com/2010/12/using-finite-state-transducers-in.html)
250
/// work on incorporating transducers in Lucene.
251
///
252
/// However, my work would also not have been possible without the hard work
253
/// of many academics, especially
254
/// [Jan Daciuk](http://galaxy.eti.pg.gda.pl/katedry/kiw/pracownicy/Jan.Daciuk/personal/).
255
///
256
/// * [Incremental construction of minimal acyclic finite-state automata](https://www.mitpressjournals.org/doi/pdfplus/10.1162/089120100561601)
257
///   (Section 3 provides a decent overview of the algorithm used to construct
258
///   transducers in this crate, assuming all outputs are `0`.)
259
/// * [Direct Construction of Minimal Acyclic Subsequential Transducers](https://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.24.3698&rep=rep1&type=pdf)
260
///   (The whole thing. The proof is dense but illuminating. The algorithm at
261
///   the end is the money shot, namely, it incorporates output values.)
262
/// * [Experiments with Automata Compression](https://www.researchgate.net/profile/Jiri-Dvorsky/publication/221568039_Word_Random_Access_Compression/links/0c96052c095630d5b3000000/Word-Random-Access-Compression.pdf#page=116), [Smaller Representation of Finite State Automata](https://www.cs.put.poznan.pl/dweiss/site/publications/download/fsacomp.pdf)
263
///   (various compression techniques for representing states/transitions)
264
/// * [Jan Daciuk's dissertation](http://www.pg.gda.pl/~jandac/thesis.ps.gz)
265
///   (excellent for in depth overview)
266
/// * [Comparison of Construction Algorithms for Minimal, Acyclic, Deterministic, Finite-State Automata from Sets of Strings](https://www.cs.mun.ca/~harold/Courses/Old/CS4750/Diary/q3p2qx4lv71m5vew.pdf)
267
///   (excellent for surface level overview)
268
#[derive(Clone)]
269
pub struct Fst<D> {
270
    meta: Meta,
271
    data: D,
272
}
273
274
#[derive(Debug, Clone)]
275
struct Meta {
276
    version: u64,
277
    root_addr: CompiledAddr,
278
    ty: FstType,
279
    len: usize,
280
    /// A checksum is missing when the FST version is <= 2. (Checksums were
281
    /// added in version 3.)
282
    checksum: Option<u32>,
283
}
284
285
impl Fst<Vec<u8>> {
286
    /// Create a new FST from an iterator of lexicographically ordered byte
287
    /// strings. Every key's value is set to `0`.
288
    ///
289
    /// If the iterator does not yield values in lexicographic order, then an
290
    /// error is returned.
291
    ///
292
    /// Note that this is a convenience function to build an FST in memory.
293
    /// To build an FST that streams to an arbitrary `io::Write`, use
294
    /// `raw::Builder`.
295
0
    pub fn from_iter_set<K, I>(iter: I) -> Result<Fst<Vec<u8>>>
296
0
    where
297
0
        K: AsRef<[u8]>,
298
0
        I: IntoIterator<Item = K>,
299
    {
300
0
        let mut builder = Builder::memory();
301
0
        for k in iter {
302
0
            builder.add(k)?;
303
        }
304
0
        Ok(builder.into_fst())
305
0
    }
306
307
    /// Create a new FST from an iterator of lexicographically ordered byte
308
    /// strings. The iterator should consist of tuples, where the first element
309
    /// is the byte string and the second element is its corresponding value.
310
    ///
311
    /// If the iterator does not yield unique keys in lexicographic order, then
312
    /// an error is returned.
313
    ///
314
    /// Note that this is a convenience function to build an FST in memory.
315
    /// To build an FST that streams to an arbitrary `io::Write`, use
316
    /// `raw::Builder`.
317
0
    pub fn from_iter_map<K, I>(iter: I) -> Result<Fst<Vec<u8>>>
318
0
    where
319
0
        K: AsRef<[u8]>,
320
0
        I: IntoIterator<Item = (K, u64)>,
321
    {
322
0
        let mut builder = Builder::memory();
323
0
        for (k, v) in iter {
324
0
            builder.insert(k, v)?;
325
        }
326
0
        Ok(builder.into_fst())
327
0
    }
328
}
329
330
impl<D: AsRef<[u8]>> Fst<D> {
331
    /// Creates a transducer from its representation as a raw byte sequence.
332
    ///
333
    /// This operation is intentionally very cheap (no allocations and no
334
    /// copies). In particular, no verification on the integrity of the
335
    /// FST is performed. Callers may opt into integrity checks via the
336
    /// [`Fst::verify`](struct.Fst.html#method.verify) method.
337
    ///
338
    /// The fst must have been written with a compatible finite state
339
    /// transducer builder (`Builder` qualifies). If the format is invalid or
340
    /// if there is a mismatch between the API version of this library and the
341
    /// fst, then an error is returned.
342
    #[inline]
343
0
    pub fn new(data: D) -> Result<Fst<D>> {
344
0
        let bytes = data.as_ref();
345
0
        if bytes.len() < 36 {
346
0
            return Err(Error::Format { size: bytes.len() }.into());
347
0
        }
348
        // The read_u64 unwraps below are OK because they can never fail.
349
        // They can only fail when there is an IO error or if there is an
350
        // unexpected EOF. However, we are reading from a byte slice (no
351
        // IO errors possible) and we've confirmed the byte slice is at least
352
        // N bytes (no unexpected EOF).
353
0
        let version = bytes::read_u64_le(&bytes);
354
0
        if version == 0 || version > VERSION {
355
0
            return Err(
356
0
                Error::Version { expected: VERSION, got: version }.into()
357
0
            );
358
0
        }
359
0
        let ty = bytes::read_u64_le(&bytes[8..]);
360
361
0
        let (end, checksum) = if version <= 2 {
362
0
            (bytes.len(), None)
363
        } else {
364
0
            let checksum = bytes::read_u32_le(&bytes[bytes.len() - 4..]);
365
0
            (bytes.len() - 4, Some(checksum))
366
        };
367
0
        let root_addr = {
368
0
            let last = &bytes[end - 8..];
369
0
            u64_to_usize(bytes::read_u64_le(last))
370
        };
371
0
        let len = {
372
0
            let last2 = &bytes[end - 16..];
373
0
            u64_to_usize(bytes::read_u64_le(last2))
374
        };
375
        // The root node is always the last node written, so its address should
376
        // be near the end. After the root node is written, we still have to
377
        // write the root *address* and the number of keys in the FST, along
378
        // with the checksum. That's 20 bytes. The extra byte used below (21
379
        // and not 20) comes from the fact that the root address points to
380
        // the last byte in the root node, rather than the byte immediately
381
        // following the root node.
382
        //
383
        // If this check passes, it is still possible that the FST is invalid
384
        // but probably unlikely. If this check reports a false positive, then
385
        // the program will probably panic. In the worst case, the FST will
386
        // operate but be subtly wrong. (This would require the bytes to be in
387
        // a format expected by an FST, which is incredibly unlikely.)
388
        //
389
        // The special check for EMPTY_ADDRESS is needed since an empty FST
390
        // has a root node that is empty and final, which means it has the
391
        // special address `0`. In that case, the FST is the smallest it can
392
        // be: the version, type, root address and number of nodes. That's
393
        // 36 bytes (8 byte u64 each).
394
        //
395
        // And finally, our calculation changes somewhat based on version.
396
        // If the FST version is less than 3, then it does not have a checksum.
397
0
        let (empty_total, addr_offset) =
398
0
            if version <= 2 { (32, 17) } else { (36, 21) };
399
0
        if (root_addr == EMPTY_ADDRESS && bytes.len() != empty_total)
400
0
            && root_addr + addr_offset != bytes.len()
401
        {
402
0
            return Err(Error::Format { size: bytes.len() }.into());
403
0
        }
404
0
        let meta = Meta { version, root_addr, ty, len, checksum };
405
0
        Ok(Fst { meta, data })
406
0
    }
407
408
    /// Retrieves the value associated with a key.
409
    ///
410
    /// If the key does not exist, then `None` is returned.
411
    #[inline]
412
0
    pub fn get<B: AsRef<[u8]>>(&self, key: B) -> Option<Output> {
413
0
        self.as_ref().get(key.as_ref())
414
0
    }
415
416
    /// Returns true if and only if the given key is in this FST.
417
    #[inline]
418
0
    pub fn contains_key<B: AsRef<[u8]>>(&self, key: B) -> bool {
419
0
        self.as_ref().contains_key(key.as_ref())
420
0
    }
421
422
    /// Retrieves the key associated with the given value.
423
    ///
424
    /// This is like `get_key_into`, but will return the key itself without
425
    /// allowing the caller to reuse an allocation.
426
    ///
427
    /// If the given value does not exist, then `None` is returned.
428
    ///
429
    /// The values in this FST are not monotonically increasing when sorted
430
    /// lexicographically by key, then this routine has unspecified behavior.
431
    #[inline]
432
0
    pub fn get_key(&self, value: u64) -> Option<Vec<u8>> {
433
0
        let mut key = vec![];
434
0
        if self.get_key_into(value, &mut key) {
435
0
            Some(key)
436
        } else {
437
0
            None
438
        }
439
0
    }
440
441
    /// Retrieves the key associated with the given value.
442
    ///
443
    /// If the given value does not exist, then `false` is returned. In this
444
    /// case, the contents of `key` are unspecified.
445
    ///
446
    /// The given buffer is not clearer before the key is written to it.
447
    ///
448
    /// The values in this FST are not monotonically increasing when sorted
449
    /// lexicographically by key, then this routine has unspecified behavior.
450
    #[inline]
451
0
    pub fn get_key_into(&self, value: u64, key: &mut Vec<u8>) -> bool {
452
0
        self.as_ref().get_key_into(value, key)
453
0
    }
454
455
    /// Return a lexicographically ordered stream of all key-value pairs in
456
    /// this fst.
457
    #[inline]
458
0
    pub fn stream(&self) -> Stream<'_> {
459
0
        StreamBuilder::new(self.as_ref(), AlwaysMatch).into_stream()
460
0
    }
461
462
    /// Return a builder for range queries.
463
    ///
464
    /// A range query returns a subset of key-value pairs in this fst in a
465
    /// range given in lexicographic order.
466
    #[inline]
467
0
    pub fn range(&self) -> StreamBuilder<'_> {
468
0
        StreamBuilder::new(self.as_ref(), AlwaysMatch)
469
0
    }
470
471
    /// Executes an automaton on the keys of this FST.
472
    #[inline]
473
0
    pub fn search<A: Automaton>(&self, aut: A) -> StreamBuilder<'_, A> {
474
0
        StreamBuilder::new(self.as_ref(), aut)
475
0
    }
476
477
    /// Executes an automaton on the keys of this FST and yields matching
478
    /// keys along with the corresponding matching states in the given
479
    /// automaton.
480
    #[inline]
481
0
    pub fn search_with_state<A: Automaton>(
482
0
        &self,
483
0
        aut: A,
484
0
    ) -> StreamWithStateBuilder<'_, A> {
485
0
        StreamWithStateBuilder::new(self.as_ref(), aut)
486
0
    }
487
488
    /// Returns the number of keys in this fst.
489
    #[inline]
490
0
    pub fn len(&self) -> usize {
491
0
        self.as_ref().len()
492
0
    }
493
494
    /// Returns true if and only if this fst has no keys.
495
    #[inline]
496
0
    pub fn is_empty(&self) -> bool {
497
0
        self.as_ref().is_empty()
498
0
    }
499
500
    /// Returns the number of bytes used by this fst.
501
    #[inline]
502
0
    pub fn size(&self) -> usize {
503
0
        self.as_ref().size()
504
0
    }
505
506
    /// Attempts to verify this FST by computing its checksum.
507
    ///
508
    /// This will scan over all of the bytes in the underlying FST, so this
509
    /// may be an expensive operation depending on the size of the FST.
510
    ///
511
    /// This returns an error in two cases:
512
    ///
513
    /// 1. When a checksum does not exist, which is the case for FSTs that were
514
    ///    produced by the `fst` crate before version `0.4`.
515
    /// 2. When the checksum in the FST does not match the computed checksum
516
    ///    performed by this procedure.
517
    #[inline]
518
0
    pub fn verify(&self) -> Result<()> {
519
        use crate::raw::crc32::CheckSummer;
520
521
0
        let expected = match self.as_ref().meta.checksum {
522
0
            None => return Err(Error::ChecksumMissing.into()),
523
0
            Some(expected) => expected,
524
        };
525
0
        let mut summer = CheckSummer::new();
526
0
        summer.update(&self.as_bytes()[..self.as_bytes().len() - 4]);
527
0
        let got = summer.masked();
528
0
        if expected == got {
529
0
            return Ok(());
530
0
        }
531
0
        Err(Error::ChecksumMismatch { expected, got }.into())
532
0
    }
533
534
    /// Creates a new fst operation with this fst added to it.
535
    ///
536
    /// The `OpBuilder` type can be used to add additional fst streams
537
    /// and perform set operations like union, intersection, difference and
538
    /// symmetric difference on the keys of the fst. These set operations also
539
    /// allow one to specify how conflicting values are merged in the stream.
540
    #[inline]
541
0
    pub fn op(&self) -> OpBuilder<'_> {
542
0
        OpBuilder::new().add(self)
543
0
    }
544
545
    /// Returns true if and only if the `self` fst is disjoint with the fst
546
    /// `stream`.
547
    ///
548
    /// `stream` must be a lexicographically ordered sequence of byte strings
549
    /// with associated values.
550
    #[inline]
551
0
    pub fn is_disjoint<'f, I, S>(&self, stream: I) -> bool
552
0
    where
553
0
        I: for<'a> IntoStreamer<'a, Into = S, Item = (&'a [u8], Output)>,
554
0
        S: 'f + for<'a> Streamer<'a, Item = (&'a [u8], Output)>,
555
    {
556
0
        self.op().add(stream).intersection().next().is_none()
557
0
    }
558
559
    /// Returns true if and only if the `self` fst is a subset of the fst
560
    /// `stream`.
561
    ///
562
    /// `stream` must be a lexicographically ordered sequence of byte strings
563
    /// with associated values.
564
    #[inline]
565
0
    pub fn is_subset<'f, I, S>(&self, stream: I) -> bool
566
0
    where
567
0
        I: for<'a> IntoStreamer<'a, Into = S, Item = (&'a [u8], Output)>,
568
0
        S: 'f + for<'a> Streamer<'a, Item = (&'a [u8], Output)>,
569
    {
570
0
        let mut op = self.op().add(stream).intersection();
571
0
        let mut count = 0;
572
0
        while let Some(_) = op.next() {
573
0
            count += 1;
574
0
        }
575
0
        count == self.len()
576
0
    }
577
578
    /// Returns true if and only if the `self` fst is a superset of the fst
579
    /// `stream`.
580
    ///
581
    /// `stream` must be a lexicographically ordered sequence of byte strings
582
    /// with associated values.
583
    #[inline]
584
0
    pub fn is_superset<'f, I, S>(&self, stream: I) -> bool
585
0
    where
586
0
        I: for<'a> IntoStreamer<'a, Into = S, Item = (&'a [u8], Output)>,
587
0
        S: 'f + for<'a> Streamer<'a, Item = (&'a [u8], Output)>,
588
    {
589
0
        let mut op = self.op().add(stream).union();
590
0
        let mut count = 0;
591
0
        while let Some(_) = op.next() {
592
0
            count += 1;
593
0
        }
594
0
        count == self.len()
595
0
    }
596
597
    /// Returns the underlying type of this fst.
598
    ///
599
    /// FstType is a convention used to indicate the type of the underlying
600
    /// transducer.
601
    ///
602
    /// This crate reserves the range 0-255 (inclusive) but currently leaves
603
    /// the meaning of 0-255 unspecified.
604
    #[inline]
605
0
    pub fn fst_type(&self) -> FstType {
606
0
        self.as_ref().fst_type()
607
0
    }
608
609
    /// Returns the root node of this fst.
610
    #[inline]
611
0
    pub fn root(&self) -> Node<'_> {
612
0
        self.as_ref().root()
613
0
    }
614
615
    /// Returns the node at the given address.
616
    ///
617
    /// Node addresses can be obtained by reading transitions on `Node` values.
618
    #[inline]
619
0
    pub fn node(&self, addr: CompiledAddr) -> Node<'_> {
620
0
        self.as_ref().node(addr)
621
0
    }
622
623
    /// Returns a copy of the binary contents of this FST.
624
    #[inline]
625
0
    pub fn to_vec(&self) -> Vec<u8> {
626
0
        self.as_ref().to_vec()
627
0
    }
628
629
    /// Returns the binary contents of this FST.
630
    #[inline]
631
0
    pub fn as_bytes(&self) -> &[u8] {
632
0
        self.as_ref().as_bytes()
633
0
    }
634
635
    #[inline]
636
0
    fn as_ref(&self) -> FstRef {
637
0
        FstRef { meta: &self.meta, data: self.data.as_ref() }
638
0
    }
639
}
640
641
impl<D> Fst<D> {
642
    /// Returns the underlying data which constitutes the FST itself.
643
    #[inline]
644
0
    pub fn into_inner(self) -> D {
645
0
        self.data
646
0
    }
647
648
    /// Returns a borrow to the underlying data which constitutes the FST itself.
649
    #[inline]
650
0
    pub fn as_inner(&self) -> &D {
651
0
        &self.data
652
0
    }
653
654
    /// Maps the underlying data of the fst to another data type.
655
    #[inline]
656
0
    pub fn map_data<F, T>(self, mut f: F) -> Result<Fst<T>>
657
0
    where
658
0
        F: FnMut(D) -> T,
659
0
        T: AsRef<[u8]>,
660
    {
661
0
        Fst::new(f(self.into_inner()))
662
0
    }
663
}
664
665
impl<'a, 'f, D: AsRef<[u8]>> IntoStreamer<'a> for &'f Fst<D> {
666
    type Item = (&'a [u8], Output);
667
    type Into = Stream<'f>;
668
669
    #[inline]
670
0
    fn into_stream(self) -> Stream<'f> {
671
0
        StreamBuilder::new(self.as_ref(), AlwaysMatch).into_stream()
672
0
    }
673
}
674
675
struct FstRef<'f> {
676
    meta: &'f Meta,
677
    data: &'f [u8],
678
}
679
680
impl<'f> FstRef<'f> {
681
    #[inline]
682
0
    fn get(&self, key: &[u8]) -> Option<Output> {
683
0
        let mut node = self.root();
684
0
        let mut out = Output::zero();
685
0
        for &b in key {
686
0
            node = match node.find_input(b) {
687
0
                None => return None,
688
0
                Some(i) => {
689
0
                    let t = node.transition(i);
690
0
                    out = out.cat(t.out);
691
0
                    self.node(t.addr)
692
                }
693
            }
694
        }
695
0
        if !node.is_final() {
696
0
            None
697
        } else {
698
0
            Some(out.cat(node.final_output()))
699
        }
700
0
    }
701
702
    #[inline]
703
0
    fn contains_key(&self, key: &[u8]) -> bool {
704
0
        let mut node = self.root();
705
0
        for &b in key {
706
0
            node = match node.find_input(b) {
707
0
                None => return false,
708
0
                Some(i) => self.node(node.transition_addr(i)),
709
            }
710
        }
711
0
        node.is_final()
712
0
    }
713
714
    #[inline]
715
0
    fn get_key_into(&self, mut value: u64, key: &mut Vec<u8>) -> bool {
716
0
        let mut node = self.root();
717
0
        while value != 0 || !node.is_final() {
718
0
            let trans = node
719
0
                .transitions()
720
0
                .take_while(|t| t.out.value() <= value)
721
0
                .last();
722
0
            node = match trans {
723
0
                None => return false,
724
0
                Some(t) => {
725
0
                    value -= t.out.value();
726
0
                    key.push(t.inp);
727
0
                    self.node(t.addr)
728
                }
729
            };
730
        }
731
0
        true
732
0
    }
733
734
    #[inline]
735
0
    fn len(&self) -> usize {
736
0
        self.meta.len
737
0
    }
738
739
    #[inline]
740
0
    fn is_empty(&self) -> bool {
741
0
        self.meta.len == 0
742
0
    }
743
744
    #[inline]
745
0
    fn size(&self) -> usize {
746
0
        self.as_bytes().len()
747
0
    }
748
749
    #[inline]
750
0
    fn fst_type(&self) -> FstType {
751
0
        self.meta.ty
752
0
    }
753
754
    #[inline]
755
0
    fn root_addr(&self) -> CompiledAddr {
756
0
        self.meta.root_addr
757
0
    }
758
759
    #[inline]
760
0
    fn root(&self) -> Node<'f> {
761
0
        self.node(self.root_addr())
762
0
    }
763
764
    #[inline]
765
0
    fn node(&self, addr: CompiledAddr) -> Node<'f> {
766
0
        Node::new(self.meta.version, addr, self.as_bytes())
767
0
    }
768
769
    #[inline]
770
0
    fn to_vec(&self) -> Vec<u8> {
771
0
        self.as_bytes().to_vec()
772
0
    }
773
774
    #[inline]
775
0
    fn as_bytes(&self) -> &'f [u8] {
776
0
        self.data
777
0
    }
778
779
    #[inline]
780
0
    fn empty_final_output(&self) -> Option<Output> {
781
0
        let root = self.root();
782
0
        if root.is_final() {
783
0
            Some(root.final_output())
784
        } else {
785
0
            None
786
        }
787
0
    }
788
}
789
790
/// A builder for constructing range queries on streams.
791
///
792
/// Once all bounds are set, one should call `into_stream` to get a
793
/// `Stream`.
794
///
795
/// Bounds are not additive. That is, if `ge` is called twice on the same
796
/// builder, then the second setting wins.
797
///
798
/// The `A` type parameter corresponds to an optional automaton to filter
799
/// the stream. By default, no filtering is done.
800
///
801
/// The `'f` lifetime parameter refers to the lifetime of the underlying fst.
802
pub struct StreamBuilder<'f, A = AlwaysMatch> {
803
    fst: FstRef<'f>,
804
    aut: A,
805
    min: Bound,
806
    max: Bound,
807
}
808
809
impl<'f, A: Automaton> StreamBuilder<'f, A> {
810
0
    fn new(fst: FstRef<'f>, aut: A) -> StreamBuilder<'f, A> {
811
0
        StreamBuilder {
812
0
            fst,
813
0
            aut,
814
0
            min: Bound::Unbounded,
815
0
            max: Bound::Unbounded,
816
0
        }
817
0
    }
818
819
    /// Specify a greater-than-or-equal-to bound.
820
0
    pub fn ge<T: AsRef<[u8]>>(mut self, bound: T) -> StreamBuilder<'f, A> {
821
0
        self.min = Bound::Included(bound.as_ref().to_owned());
822
0
        self
823
0
    }
824
825
    /// Specify a greater-than bound.
826
0
    pub fn gt<T: AsRef<[u8]>>(mut self, bound: T) -> StreamBuilder<'f, A> {
827
0
        self.min = Bound::Excluded(bound.as_ref().to_owned());
828
0
        self
829
0
    }
830
831
    /// Specify a less-than-or-equal-to bound.
832
0
    pub fn le<T: AsRef<[u8]>>(mut self, bound: T) -> StreamBuilder<'f, A> {
833
0
        self.max = Bound::Included(bound.as_ref().to_owned());
834
0
        self
835
0
    }
836
837
    /// Specify a less-than bound.
838
0
    pub fn lt<T: AsRef<[u8]>>(mut self, bound: T) -> StreamBuilder<'f, A> {
839
0
        self.max = Bound::Excluded(bound.as_ref().to_owned());
840
0
        self
841
0
    }
842
}
843
844
impl<'a, 'f, A: Automaton> IntoStreamer<'a> for StreamBuilder<'f, A> {
845
    type Item = (&'a [u8], Output);
846
    type Into = Stream<'f, A>;
847
848
0
    fn into_stream(self) -> Stream<'f, A> {
849
0
        Stream::new(self.fst, self.aut, self.min, self.max)
850
0
    }
851
}
852
853
/// A builder for constructing range queries on streams that include automaton
854
/// states.
855
///
856
/// In general, one should use `StreamBuilder` unless you have a specific need
857
/// for accessing the states of the underlying automaton that is being used to
858
/// filter this stream.
859
///
860
/// Once all bounds are set, one should call `into_stream` to get a
861
/// `Stream`.
862
///
863
/// Bounds are not additive. That is, if `ge` is called twice on the same
864
/// builder, then the second setting wins.
865
///
866
/// The `A` type parameter corresponds to an optional automaton to filter
867
/// the stream. By default, no filtering is done.
868
///
869
/// The `'f` lifetime parameter refers to the lifetime of the underlying fst.
870
pub struct StreamWithStateBuilder<'f, A = AlwaysMatch> {
871
    fst: FstRef<'f>,
872
    aut: A,
873
    min: Bound,
874
    max: Bound,
875
}
876
877
impl<'f, A: Automaton> StreamWithStateBuilder<'f, A> {
878
0
    fn new(fst: FstRef<'f>, aut: A) -> StreamWithStateBuilder<'f, A> {
879
0
        StreamWithStateBuilder {
880
0
            fst,
881
0
            aut,
882
0
            min: Bound::Unbounded,
883
0
            max: Bound::Unbounded,
884
0
        }
885
0
    }
886
887
    /// Specify a greater-than-or-equal-to bound.
888
0
    pub fn ge<T: AsRef<[u8]>>(
889
0
        mut self,
890
0
        bound: T,
891
0
    ) -> StreamWithStateBuilder<'f, A> {
892
0
        self.min = Bound::Included(bound.as_ref().to_owned());
893
0
        self
894
0
    }
895
896
    /// Specify a greater-than bound.
897
0
    pub fn gt<T: AsRef<[u8]>>(
898
0
        mut self,
899
0
        bound: T,
900
0
    ) -> StreamWithStateBuilder<'f, A> {
901
0
        self.min = Bound::Excluded(bound.as_ref().to_owned());
902
0
        self
903
0
    }
904
905
    /// Specify a less-than-or-equal-to bound.
906
0
    pub fn le<T: AsRef<[u8]>>(
907
0
        mut self,
908
0
        bound: T,
909
0
    ) -> StreamWithStateBuilder<'f, A> {
910
0
        self.max = Bound::Included(bound.as_ref().to_owned());
911
0
        self
912
0
    }
913
914
    /// Specify a less-than bound.
915
0
    pub fn lt<T: AsRef<[u8]>>(
916
0
        mut self,
917
0
        bound: T,
918
0
    ) -> StreamWithStateBuilder<'f, A> {
919
0
        self.max = Bound::Excluded(bound.as_ref().to_owned());
920
0
        self
921
0
    }
922
}
923
924
impl<'a, 'f, A: 'a + Automaton> IntoStreamer<'a>
925
    for StreamWithStateBuilder<'f, A>
926
where
927
    A::State: Clone,
928
{
929
    type Item = (&'a [u8], Output, A::State);
930
    type Into = StreamWithState<'f, A>;
931
932
0
    fn into_stream(self) -> StreamWithState<'f, A> {
933
0
        StreamWithState::new(self.fst, self.aut, self.min, self.max)
934
0
    }
935
}
936
937
#[derive(Debug)]
938
enum Bound {
939
    Included(Vec<u8>),
940
    Excluded(Vec<u8>),
941
    Unbounded,
942
}
943
944
impl Bound {
945
    #[inline]
946
0
    fn exceeded_by(&self, inp: &[u8]) -> bool {
947
0
        match *self {
948
0
            Bound::Included(ref v) => inp > v,
949
0
            Bound::Excluded(ref v) => inp >= v,
950
0
            Bound::Unbounded => false,
951
        }
952
0
    }
953
954
    #[inline]
955
0
    fn is_empty(&self) -> bool {
956
0
        match *self {
957
0
            Bound::Included(ref v) => v.is_empty(),
958
0
            Bound::Excluded(ref v) => v.is_empty(),
959
0
            Bound::Unbounded => true,
960
        }
961
0
    }
962
963
    #[inline]
964
0
    fn is_inclusive(&self) -> bool {
965
0
        match *self {
966
0
            Bound::Excluded(_) => false,
967
0
            _ => true,
968
        }
969
0
    }
970
}
971
972
/// A lexicographically ordered stream of key-value pairs from an fst.
973
///
974
/// The `A` type parameter corresponds to an optional automaton to filter
975
/// the stream. By default, no filtering is done.
976
///
977
/// The `'f` lifetime parameter refers to the lifetime of the underlying fst.
978
pub struct Stream<'f, A: Automaton = AlwaysMatch>(StreamWithState<'f, A>);
979
980
impl<'f, A: Automaton> Stream<'f, A> {
981
0
    fn new(fst: FstRef<'f>, aut: A, min: Bound, max: Bound) -> Stream<'f, A> {
982
0
        Stream(StreamWithState::new(fst, aut, min, max))
983
0
    }
984
985
    /// Convert this stream into a vector of byte strings and outputs.
986
    ///
987
    /// Note that this creates a new allocation for every key in the stream.
988
0
    pub fn into_byte_vec(mut self) -> Vec<(Vec<u8>, u64)> {
989
0
        let mut vs = vec![];
990
0
        while let Some((k, v)) = self.next() {
991
0
            vs.push((k.to_vec(), v.value()));
992
0
        }
993
0
        vs
994
0
    }
995
996
    /// Convert this stream into a vector of Unicode strings and outputs.
997
    ///
998
    /// If any key is not valid UTF-8, then iteration on the stream is stopped
999
    /// and a UTF-8 decoding error is returned.
1000
    ///
1001
    /// Note that this creates a new allocation for every key in the stream.
1002
0
    pub fn into_str_vec(mut self) -> Result<Vec<(String, u64)>> {
1003
0
        let mut vs = vec![];
1004
0
        while let Some((k, v)) = self.next() {
1005
0
            let k = String::from_utf8(k.to_vec()).map_err(Error::from)?;
1006
0
            vs.push((k, v.value()));
1007
        }
1008
0
        Ok(vs)
1009
0
    }
1010
1011
    /// Convert this stream into a vector of byte strings.
1012
    ///
1013
    /// Note that this creates a new allocation for every key in the stream.
1014
0
    pub fn into_byte_keys(mut self) -> Vec<Vec<u8>> {
1015
0
        let mut vs = vec![];
1016
0
        while let Some((k, _)) = self.next() {
1017
0
            vs.push(k.to_vec());
1018
0
        }
1019
0
        vs
1020
0
    }
1021
1022
    /// Convert this stream into a vector of Unicode strings.
1023
    ///
1024
    /// If any key is not valid UTF-8, then iteration on the stream is stopped
1025
    /// and a UTF-8 decoding error is returned.
1026
    ///
1027
    /// Note that this creates a new allocation for every key in the stream.
1028
0
    pub fn into_str_keys(mut self) -> Result<Vec<String>> {
1029
0
        let mut vs = vec![];
1030
0
        while let Some((k, _)) = self.next() {
1031
0
            let k = String::from_utf8(k.to_vec()).map_err(Error::from)?;
1032
0
            vs.push(k);
1033
        }
1034
0
        Ok(vs)
1035
0
    }
1036
1037
    /// Convert this stream into a vector of outputs.
1038
0
    pub fn into_values(mut self) -> Vec<u64> {
1039
0
        let mut vs = vec![];
1040
0
        while let Some((_, v)) = self.next() {
1041
0
            vs.push(v.value());
1042
0
        }
1043
0
        vs
1044
0
    }
1045
}
1046
1047
impl<'f, 'a, A: Automaton> Streamer<'a> for Stream<'f, A> {
1048
    type Item = (&'a [u8], Output);
1049
1050
0
    fn next(&'a mut self) -> Option<(&'a [u8], Output)> {
1051
0
        self.0.next_with(|_| ()).map(|(key, out, _)| (key, out))
1052
0
    }
1053
}
1054
1055
/// A lexicographically ordered stream of key-value-state triples from an fst
1056
/// and an automaton.
1057
///
1058
/// The key-values are from the underyling FSTP while the states are from the
1059
/// automaton.
1060
///
1061
/// The `A` type parameter corresponds to an optional automaton to filter
1062
/// the stream. By default, no filtering is done.
1063
///
1064
/// The `'m` lifetime parameter refers to the lifetime of the underlying map.
1065
pub struct StreamWithState<'f, A = AlwaysMatch>
1066
where
1067
    A: Automaton,
1068
{
1069
    fst: FstRef<'f>,
1070
    aut: A,
1071
    inp: Vec<u8>,
1072
    empty_output: Option<Output>,
1073
    stack: Vec<StreamState<'f, A::State>>,
1074
    end_at: Bound,
1075
}
1076
1077
#[derive(Clone, Debug)]
1078
struct StreamState<'f, S> {
1079
    node: Node<'f>,
1080
    trans: usize,
1081
    out: Output,
1082
    aut_state: S,
1083
}
1084
1085
impl<'f, A: Automaton> StreamWithState<'f, A> {
1086
0
    fn new(
1087
0
        fst: FstRef<'f>,
1088
0
        aut: A,
1089
0
        min: Bound,
1090
0
        max: Bound,
1091
0
    ) -> StreamWithState<'f, A> {
1092
0
        let mut rdr = StreamWithState {
1093
0
            fst,
1094
0
            aut,
1095
0
            inp: Vec::with_capacity(16),
1096
0
            empty_output: None,
1097
0
            stack: vec![],
1098
0
            end_at: max,
1099
0
        };
1100
0
        rdr.seek_min(min);
1101
0
        rdr
1102
0
    }
1103
1104
    /// Seeks the underlying stream such that the next key to be read is the
1105
    /// smallest key in the underlying fst that satisfies the given minimum
1106
    /// bound.
1107
    ///
1108
    /// This theoretically should be straight-forward, but we need to make
1109
    /// sure our stack is correct, which includes accounting for automaton
1110
    /// states.
1111
0
    fn seek_min(&mut self, min: Bound) {
1112
0
        if min.is_empty() {
1113
0
            if min.is_inclusive() {
1114
0
                self.empty_output = self.fst.empty_final_output();
1115
0
            }
1116
0
            self.stack = vec![StreamState {
1117
0
                node: self.fst.root(),
1118
0
                trans: 0,
1119
0
                out: Output::zero(),
1120
0
                aut_state: self.aut.start(),
1121
0
            }];
1122
0
            return;
1123
0
        }
1124
0
        let (key, inclusive) = match min {
1125
0
            Bound::Excluded(ref min) => (min, false),
1126
0
            Bound::Included(ref min) => (min, true),
1127
0
            Bound::Unbounded => unreachable!(),
1128
        };
1129
        // At this point, we need to find the starting location of `min` in
1130
        // the FST. However, as we search, we need to maintain a stack of
1131
        // reader states so that the reader can pick up where we left off.
1132
        // N.B. We do not necessarily need to stop in a final state, unlike
1133
        // the one-off `find` method. For the example, the given bound might
1134
        // not actually exist in the FST.
1135
0
        let mut node = self.fst.root();
1136
0
        let mut out = Output::zero();
1137
0
        let mut aut_state = self.aut.start();
1138
0
        for &b in key {
1139
0
            match node.find_input(b) {
1140
0
                Some(i) => {
1141
0
                    let t = node.transition(i);
1142
0
                    let prev_state = aut_state;
1143
0
                    aut_state = self.aut.accept(&prev_state, b);
1144
0
                    self.inp.push(b);
1145
0
                    self.stack.push(StreamState {
1146
0
                        node,
1147
0
                        trans: i + 1,
1148
0
                        out,
1149
0
                        aut_state: prev_state,
1150
0
                    });
1151
0
                    out = out.cat(t.out);
1152
0
                    node = self.fst.node(t.addr);
1153
0
                }
1154
                None => {
1155
                    // This is a little tricky. We're in this case if the
1156
                    // given bound is not a prefix of any key in the FST.
1157
                    // Since this is a minimum bound, we need to find the
1158
                    // first transition in this node that proceeds the current
1159
                    // input byte.
1160
0
                    self.stack.push(StreamState {
1161
0
                        node,
1162
0
                        trans: node
1163
0
                            .transitions()
1164
0
                            .position(|t| t.inp > b)
1165
0
                            .unwrap_or(node.len()),
1166
0
                        out,
1167
0
                        aut_state,
1168
                    });
1169
0
                    return;
1170
                }
1171
            }
1172
        }
1173
0
        if !self.stack.is_empty() {
1174
0
            let last = self.stack.len() - 1;
1175
0
            if inclusive {
1176
0
                self.stack[last].trans -= 1;
1177
0
                self.inp.pop();
1178
0
            } else {
1179
0
                let node = self.stack[last].node;
1180
0
                let trans = self.stack[last].trans;
1181
0
                self.stack.push(StreamState {
1182
0
                    node: self.fst.node(node.transition(trans - 1).addr),
1183
0
                    trans: 0,
1184
0
                    out,
1185
0
                    aut_state,
1186
0
                });
1187
0
            }
1188
0
        }
1189
0
    }
1190
1191
0
    fn next_with<T>(
1192
0
        &mut self,
1193
0
        mut map: impl FnMut(&A::State) -> T,
1194
0
    ) -> Option<(&[u8], Output, T)> {
1195
0
        if let Some(out) = self.empty_output.take() {
1196
0
            if self.end_at.exceeded_by(&[]) {
1197
0
                self.stack.clear();
1198
0
                return None;
1199
0
            }
1200
1201
0
            let start = self.aut.start();
1202
0
            if self.aut.is_match(&start) {
1203
0
                return Some((&[], out, map(&start)));
1204
0
            }
1205
0
        }
1206
0
        while let Some(state) = self.stack.pop() {
1207
0
            if state.trans >= state.node.len()
1208
0
                || !self.aut.can_match(&state.aut_state)
1209
            {
1210
0
                if state.node.addr() != self.fst.root_addr() {
1211
0
                    self.inp.pop().unwrap();
1212
0
                }
1213
0
                continue;
1214
0
            }
1215
0
            let trans = state.node.transition(state.trans);
1216
0
            let out = state.out.cat(trans.out);
1217
0
            let next_state = self.aut.accept(&state.aut_state, trans.inp);
1218
0
            let t = map(&next_state);
1219
0
            let mut is_match = self.aut.is_match(&next_state);
1220
0
            let next_node = self.fst.node(trans.addr);
1221
0
            self.inp.push(trans.inp);
1222
0
            if next_node.is_final() {
1223
0
                if let Some(eof_state) = self.aut.accept_eof(&next_state) {
1224
0
                    is_match = self.aut.is_match(&eof_state);
1225
0
                }
1226
0
            }
1227
0
            self.stack.push(StreamState { trans: state.trans + 1, ..state });
1228
0
            self.stack.push(StreamState {
1229
0
                node: next_node,
1230
0
                trans: 0,
1231
0
                out,
1232
0
                aut_state: next_state,
1233
0
            });
1234
0
            if self.end_at.exceeded_by(&self.inp) {
1235
                // We are done, forever.
1236
0
                self.stack.clear();
1237
0
                return None;
1238
0
            }
1239
0
            if next_node.is_final() && is_match {
1240
0
                return Some((
1241
0
                    &self.inp,
1242
0
                    out.cat(next_node.final_output()),
1243
0
                    t,
1244
0
                ));
1245
0
            }
1246
        }
1247
0
        None
1248
0
    }
1249
}
1250
1251
impl<'a, 'f, A: 'a + Automaton> Streamer<'a> for StreamWithState<'f, A>
1252
where
1253
    A::State: Clone,
1254
{
1255
    type Item = (&'a [u8], Output, A::State);
1256
1257
0
    fn next(&'a mut self) -> Option<(&'a [u8], Output, A::State)> {
1258
0
        self.next_with(|state| state.clone())
1259
0
    }
1260
}
1261
1262
/// An output is a value that is associated with a key in a finite state
1263
/// transducer.
1264
///
1265
/// Note that outputs must satisfy an algebra. Namely, it must have an additive
1266
/// identity and the following binary operations defined: `prefix`,
1267
/// `concatenation` and `subtraction`. `prefix` and `concatenation` are
1268
/// commutative while `subtraction` is not. `subtraction` is only defined on
1269
/// pairs of operands where the first operand is greater than or equal to the
1270
/// second operand.
1271
///
1272
/// Currently, output values must be `u64`. However, in theory, an output value
1273
/// can be anything that satisfies the above algebra. Future versions of this
1274
/// crate may make outputs generic on this algebra.
1275
#[derive(Copy, Clone, Debug, Hash, Eq, Ord, PartialEq, PartialOrd)]
1276
pub struct Output(u64);
1277
1278
impl Output {
1279
    /// Create a new output from a `u64`.
1280
    #[inline]
1281
0
    pub fn new(v: u64) -> Output {
1282
0
        Output(v)
1283
0
    }
1284
1285
    /// Create a zero output.
1286
    #[inline]
1287
0
    pub fn zero() -> Output {
1288
0
        Output(0)
1289
0
    }
1290
1291
    /// Retrieve the value inside this output.
1292
    #[inline]
1293
0
    pub fn value(self) -> u64 {
1294
0
        self.0
1295
0
    }
1296
1297
    /// Returns true if this is a zero output.
1298
    #[inline]
1299
0
    pub fn is_zero(self) -> bool {
1300
0
        self.0 == 0
1301
0
    }
1302
1303
    /// Returns the prefix of this output and `o`.
1304
    #[inline]
1305
0
    pub fn prefix(self, o: Output) -> Output {
1306
0
        Output(cmp::min(self.0, o.0))
1307
0
    }
1308
1309
    /// Returns the concatenation of this output and `o`.
1310
    #[inline]
1311
0
    pub fn cat(self, o: Output) -> Output {
1312
0
        Output(self.0 + o.0)
1313
0
    }
1314
1315
    /// Returns the subtraction of `o` from this output.
1316
    ///
1317
    /// This function panics if `self < o`.
1318
    #[inline]
1319
0
    pub fn sub(self, o: Output) -> Output {
1320
0
        Output(
1321
0
            self.0
1322
0
                .checked_sub(o.0)
1323
0
                .expect("BUG: underflow subtraction not allowed"),
1324
0
        )
1325
0
    }
1326
}
1327
1328
/// A transition from one note to another.
1329
#[derive(Copy, Clone, Hash, Eq, PartialEq)]
1330
pub struct Transition {
1331
    /// The byte input associated with this transition.
1332
    pub inp: u8,
1333
    /// The output associated with this transition.
1334
    pub out: Output,
1335
    /// The address of the node that this transition points to.
1336
    pub addr: CompiledAddr,
1337
}
1338
1339
impl Default for Transition {
1340
    #[inline]
1341
0
    fn default() -> Transition {
1342
0
        Transition { inp: 0, out: Output::zero(), addr: NONE_ADDRESS }
1343
0
    }
1344
}
1345
1346
impl fmt::Debug for Transition {
1347
0
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1348
0
        if self.out.is_zero() {
1349
0
            write!(f, "{} -> {}", self.inp as char, self.addr)
1350
        } else {
1351
0
            write!(
1352
0
                f,
1353
                "({}, {}) -> {}",
1354
0
                self.inp as char,
1355
0
                self.out.value(),
1356
                self.addr
1357
            )
1358
        }
1359
0
    }
1360
}
1361
1362
#[inline]
1363
#[cfg(target_pointer_width = "64")]
1364
0
fn u64_to_usize(n: u64) -> usize {
1365
0
    n as usize
1366
0
}
1367
1368
#[inline]
1369
#[cfg(not(target_pointer_width = "64"))]
1370
fn u64_to_usize(n: u64) -> usize {
1371
    if n > std::usize::MAX as u64 {
1372
        panic!(
1373
            "\
1374
Cannot convert node address {} to a pointer sized variable. If this FST
1375
is very large and was generated on a system with a larger pointer size
1376
than this system, then it is not possible to read this FST on this
1377
system.",
1378
            n
1379
        );
1380
    }
1381
    n as usize
1382
}