#![deny(missing_docs)]
#![cfg_attr(docsrs, feature(doc_cfg))]
#![no_std]
#[cfg(not(feature = "alloc"))]
compile_error!("`alloc` feature is currently required to build this crate");
#[cfg(target_pointer_width = "16")]
compile_error!("`target_pointer_width` must be larger than or equal to 32");
#[macro_use]
extern crate alloc;
mod build_helper;
pub mod bytewise;
pub mod charwise;
pub mod errors;
mod intpack;
mod nfa_builder;
mod serializer;
mod utils;
use core::num::NonZeroU32;
use alloc::vec::Vec;
use build_helper::BuildHelper;
pub use bytewise::{DoubleArrayAhoCorasick, DoubleArrayAhoCorasickBuilder};
pub use charwise::{CharwiseDoubleArrayAhoCorasick, CharwiseDoubleArrayAhoCorasickBuilder};
pub use serializer::Serializable;
#[derive(Copy, Clone, Debug, Eq, Hash, PartialEq)]
struct Output<V> {
value: V,
length: u32,
parent: Option<NonZeroU32>,
}
impl<V> Output<V>
where
V: Copy,
{
#[allow(clippy::missing_const_for_fn)]
#[inline(always)]
pub fn new(value: V, length: u32, parent: Option<NonZeroU32>) -> Self {
Self {
value,
length,
parent,
}
}
#[allow(clippy::missing_const_for_fn)]
#[inline(always)]
pub fn value(self) -> V {
self.value
}
#[allow(clippy::missing_const_for_fn)]
#[inline(always)]
pub fn length(self) -> u32 {
self.length
}
#[allow(clippy::missing_const_for_fn)]
#[inline(always)]
pub fn parent(self) -> Option<NonZeroU32> {
self.parent
}
}
impl<V> Serializable for Output<V>
where
V: Serializable,
{
#[inline(always)]
fn serialize_to_vec(&self, dst: &mut Vec<u8>) {
self.value.serialize_to_vec(dst);
self.length.serialize_to_vec(dst);
self.parent.serialize_to_vec(dst);
}
#[inline(always)]
fn deserialize_from_slice(src: &[u8]) -> (Self, &[u8]) {
let (value, src) = V::deserialize_from_slice(src);
let (length, src) = u32::deserialize_from_slice(src);
let (parent, src) = Option::<NonZeroU32>::deserialize_from_slice(src);
(
Self {
value,
length,
parent,
},
src,
)
}
#[inline(always)]
fn serialized_bytes() -> usize {
V::serialized_bytes() + u32::serialized_bytes() + Option::<NonZeroU32>::serialized_bytes()
}
}
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
pub struct Match<V> {
length: usize,
end: usize,
value: V,
}
impl<V> Match<V>
where
V: Copy,
{
#[allow(clippy::missing_const_for_fn)]
#[inline(always)]
#[must_use]
pub fn start(&self) -> usize {
self.end - self.length
}
#[allow(clippy::missing_const_for_fn)]
#[inline(always)]
#[must_use]
pub fn end(&self) -> usize {
self.end
}
#[allow(clippy::missing_const_for_fn)]
#[inline(always)]
#[must_use]
pub fn value(&self) -> V {
self.value
}
}
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
#[repr(u8)]
pub enum MatchKind {
Standard = 0,
LeftmostLongest = 1,
LeftmostFirst = 2,
}
impl MatchKind {
fn is_standard(self) -> bool {
self == Self::Standard
}
fn is_leftmost(self) -> bool {
self == Self::LeftmostFirst || self == Self::LeftmostLongest
}
pub(crate) fn is_leftmost_first(self) -> bool {
self == Self::LeftmostFirst
}
}
impl From<u8> for MatchKind {
fn from(src: u8) -> Self {
match src {
1 => Self::LeftmostLongest,
2 => Self::LeftmostFirst,
_ => Self::Standard,
}
}
}
impl From<MatchKind> for u8 {
fn from(src: MatchKind) -> Self {
match src {
MatchKind::Standard => 0,
MatchKind::LeftmostLongest => 1,
MatchKind::LeftmostFirst => 2,
}
}
}
impl Serializable for MatchKind {
#[inline(always)]
fn serialize_to_vec(&self, dst: &mut Vec<u8>) {
dst.push(u8::from(*self));
}
#[inline(always)]
fn deserialize_from_slice(src: &[u8]) -> (Self, &[u8]) {
(Self::from(src[0]), &src[1..])
}
#[inline(always)]
fn serialized_bytes() -> usize {
1
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_serialize_output() {
let x = Output {
value: 42u32,
length: 57,
parent: NonZeroU32::new(13),
};
let mut data = vec![];
x.serialize_to_vec(&mut data);
assert_eq!(data.len(), Output::<u32>::serialized_bytes());
let (y, rest) = Output::deserialize_from_slice(&data);
assert!(rest.is_empty());
assert_eq!(x, y);
}
#[test]
fn test_serialize_match_kind() {
let x = MatchKind::LeftmostLongest;
let mut data = vec![];
x.serialize_to_vec(&mut data);
assert_eq!(data.len(), MatchKind::serialized_bytes());
let (y, rest) = MatchKind::deserialize_from_slice(&data);
assert!(rest.is_empty());
assert_eq!(x, y);
}
}