1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
//! Implementation Notes
//!
//! This page lists some implementation notes for developers.
//!
//!
//! # `unsafe` Rust which looks like safe Rust
//!
//! In this crate, the main motivation to use `unsafe` is to suppress array
//! bounds checks (that are known to be safe according to the code review or
//! should be safe if public functions / methods are used correctly).
//!
//! However, if we use pointers, we cannot easily switch between safe and unsafe
//! Rust variants.  We chose to use "invariants" instead.  If Rust / LLVM knows
//! that an array access is safe, it skips bounds check.  So, we can put an
//! invariant to tell the optimizer that the array access is safe.  Despite that
//! generating an invariant itself is an unsafe operation, most code looks
//! like safe Rust.
//!
//! To not to miss `unsafe` invariant uses, `invariant!` macro must be placed
//! inside a `optionally_unsafe!` macro block (which is going to be an `unsafe`
//! block or a regular block depending on the configuration).
//!
//! Invariants can suppress another type of runtime check (not just array
//! bounds check): division by zero.
//!
//! A big exception is the
//! [generator's main loop](crate::generate::Generator::update).
//! Because using pointer-based block hash context access is much efficient (we
//! can even reuse pointer ranges), the structure of this loop changes
//! significantly between both implementations.
//! But still, most of the code is shared.
//!
//!
//! # Methods: Non-suffixed, `unchecked` and `internal`
//!
//! Non-suffixed version is the safest version for regular users and is safe (or
//! to be more precise, optionally unsafe).  It checks validity of
//! user-specified arguments properly.
//!
//! Still, it can be a waste of time if the user knows what he/she's doing.
//!
//! `unchecked` version is exported and is marked `unsafe`.
//! It doesn't check whether certain "Usage Constraints" are satisfied.
//! It can be useful on some specialized clustering applications.
//!
//! The crate developers also know (and/or *should* know) certain constraints
//! are satisfied already and want to avoid `unsafe` blocks as well as excess
//! argument checking.
//!
//! `internal` version is safe but not exported.  The crate developers must be
//! aware of the constraints and must satisfy them before calling.
//!
//! Note that, all `unchecked` functions are just wrappers of
//! `internal` functions.  The only purpose of `internal` is to avoid `unsafe`.
//!
//! As an exception, if a `struct` is already broken by a memory corruption
//! caused by something outside this crate or a misuse of `unchecked` functions,
//! it's not obligated to check such corruption
//! (the crate developers can assume that `struct` is not "very" broken).
//!
//! ## Links (to non-suffixed methods)
//!
//! *   [`crate::compare::BlockHashPositionArray::is_equiv`]
//! *   [`crate::compare::BlockHashPositionArray::has_common_substring`]
//! *   [`crate::compare::BlockHashPositionArray::edit_distance`]
//! *   [`crate::compare::BlockHashPositionArray::score_strings_raw`]
//! *   [`crate::compare::BlockHashPositionArray::score_strings`]
//! *   [`crate::compare::FuzzyHashCompareTarget::score_cap_on_block_hash_comparison`]
//! *   [`crate::compare::FuzzyHashCompareTarget::compare_unequal_near_eq`]
//! *   [`crate::compare::FuzzyHashCompareTarget::compare_near_eq`]
//! *   [`crate::compare::FuzzyHashCompareTarget::compare_unequal_near_lt`]
//! *   [`crate::compare::FuzzyHashCompareTarget::compare_unequal_near_gt`]
//! *   [`crate::compare::FuzzyHashCompareTarget::compare_unequal`]
//! *   [`crate::hash::FuzzyHashData::compare_unequal`]
//! *   [`crate::hash::FuzzyHashData::init_from_internals_raw`]
//! *   [`crate::hash::FuzzyHashData::new_from_internals`]
//! *   [`crate::hash::FuzzyHashData::new_from_internals_raw`]
//! *   [`crate::hash::block::BlockSize::log_from_valid`]
//! *   [`crate::hash_dual::FuzzyHashDualData::init_from_raw_form_internals_raw`]
//! *   [`crate::hash_dual::FuzzyHashDualData::new_from_raw_form_internals_raw`]