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
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
/* Copyright 2022-2023 Danny McClanahan */
/* SPDX-License-Identifier: BSD-3-Clause */
//! ???
use crate::{hs, matchers::ExpressionIndex};
use displaydoc::Display;
use thiserror::Error;
use std::{
ffi::{CStr, NulError},
os::raw::c_uint,
};
#[derive(
Debug,
Display,
Error,
Copy,
Clone,
PartialEq,
Eq,
PartialOrd,
Ord,
Hash,
num_enum::IntoPrimitive,
num_enum::FromPrimitive,
)]
#[repr(i8)]
#[ignore_extra_doc_attributes]
pub enum HyperscanError {
/// A parameter passed to this function was invalid.
///
/// This error is only returned in cases where the function can detect an
/// invalid parameter -- it cannot be relied upon to detect (for example)
/// pointers to freed memory or other invalid data.
Invalid = hs::HS_INVALID,
/// A memory allocation failed.
NoMem = hs::HS_NOMEM,
/// The engine was terminated by callback.
///
/// This return value indicates that the target buffer was partially scanned,
/// but that the callback function requested that scanning cease after a match
/// was located.
ScanTerminated = hs::HS_SCAN_TERMINATED,
/// The pattern compiler failed, and the [`CompileError`] should be
/// inspected for more detail.
CompilerError = hs::HS_COMPILER_ERROR,
/// The given database was built for a different version of Hyperscan.
DbVersionError = hs::HS_DB_VERSION_ERROR,
/// The given database was built for a different platform (i.e., CPU type).
DbPlatformError = hs::HS_DB_PLATFORM_ERROR,
/// The given database was built for a different mode of operation.
///
/// This error is returned when streaming calls are used with a block or
/// vectored database and vice versa.
DbModeError = hs::HS_DB_MODE_ERROR,
/// A parameter passed to this function was not correctly aligned.
BadAlign = hs::HS_BAD_ALIGN,
/// The memory allocator returned incorrectly aligned memory.
///
/// The memory allocator (either `malloc()` or the allocator set with @ref
/// hs_set_allocator()) did not correctly return memory suitably aligned for
/// the largest representable data type on this platform.
BadAlloc = hs::HS_BAD_ALLOC,
/// The scratch region was already in use.
///
/// This error is returned when Hyperscan is able to detect that the scratch
/// region given is already in use by another Hyperscan API call.
///
/// A separate scratch region, allocated with @ref hs_alloc_scratch() or @ref
/// hs_clone_scratch(), is required for every concurrent caller of the
/// Hyperscan API.
///
/// For example, this error might be returned when @ref hs_scan() has been
/// called inside a callback delivered by a currently-executing @ref hs_scan()
/// call using the same scratch region.
///
/// Note: Not all concurrent uses of scratch regions may be detected. This
/// error is intended as a best-effort debugging tool, not a guarantee.
ScratchInUse = hs::HS_SCRATCH_IN_USE,
/// Unsupported CPU architecture.
///
/// This error is returned when Hyperscan is able to detect that the current
/// system does not support the required instruction set.
///
/// At a minimum, Hyperscan requires Supplemental Streaming SIMD Extensions 3
/// (SSSE3).
ArchError = hs::HS_ARCH_ERROR,
/// Provided buffer was too small.
///
/// This error indicates that there was insufficient space in the buffer. The
/// call should be repeated with a larger provided buffer.
///
/// Note: in this situation, it is normal for the amount of space required to
/// be returned in the same manner as the used space would have been
/// returned if the call was successful.
InsufficientSpace = hs::HS_INSUFFICIENT_SPACE,
/// Unexpected internal error.
///
/// This error indicates that there was unexpected matching behaviors. This
/// could be related to invalid usage of stream and scratch space or invalid
/// memory operations by users.
#[num_enum(default)]
UnknownError = hs::HS_UNKNOWN_ERROR,
}
impl HyperscanError {
#[inline]
pub(crate) fn from_native(x: hs::hs_error_t) -> Result<(), Self> {
static_assertions::const_assert_eq!(0, hs::HS_SUCCESS);
if x == 0 {
Ok(())
} else {
let s: Self = (x as i8).into();
Err(s)
}
}
#[inline]
pub(crate) fn copy_from_native_compile_error(
x: hs::hs_error_t,
c: *mut hs::hs_compile_error,
) -> Result<(), HyperscanCompileError> {
match Self::from_native(x) {
Ok(()) => Ok(()),
Err(Self::CompilerError) => {
let e = CompileError::copy_from_native(unsafe { &mut *c }).unwrap();
Err(HyperscanCompileError::Compile(e))
},
Err(e) => Err(e.into()),
}
}
}
#[derive(Debug, Display, Error)]
pub enum HyperscanFlagsError {
/// A mode was created without BLOCK, STREAM, or VECTORED somehow.
InvalidDbMode,
/// SOM_LEFTMOST flag provided, but no SOM_HORIZON_* mode was specified.
SomHorizonModeRequired,
}
/// compile error(@{expression}): {message}
#[derive(Debug, Display, Error)]
pub struct CompileError {
pub message: String,
pub expression: ExpressionIndex,
}
impl CompileError {
#[inline]
pub fn copy_from_native(x: &mut hs::hs_compile_error) -> Result<Self, HyperscanError> {
let hs::hs_compile_error {
message,
expression,
} = x;
assert!(!message.is_null());
let ret = Self {
message: unsafe { CStr::from_ptr(*message) }
.to_string_lossy()
.to_string(),
expression: ExpressionIndex(*expression as c_uint),
};
HyperscanError::from_native(unsafe { hs::hs_free_compile_error(x) })?;
Ok(ret)
}
}
#[derive(Debug, Display, Error)]
pub enum HyperscanCompileError {
/// flags error: {0}
Flags(#[from] HyperscanFlagsError),
/// non-compilation error: {0}
NonCompile(#[from] HyperscanError),
/// pattern compilation error: {0}
Compile(#[from] CompileError),
/// null byte in expression: {0}
NullByte(#[from] NulError),
}
#[derive(Debug, Display, Error)]
pub enum CompressionError {
/// other error: {0}
Other(#[from] HyperscanError),
/// not enough space for {0} in buf
NoSpace(usize),
}