#![allow(clippy::use_self)] mod directory;
mod http_methods;
mod range;
mod wordlist;
use crate::input::Data;
use crate::std_ext::ops::Len;
pub use crate::std_ext::tuple::Named;
use std::collections::HashMap;
use std::fmt::{self, Display, Formatter};
use std::ops::{Deref, DerefMut};
use std::sync::atomic::AtomicUsize;
use std::sync::{Arc, RwLock};
#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};
use tracing::instrument;
pub use self::directory::DirCorpus;
pub use self::http_methods::HttpMethodsCorpus;
pub use self::range::RangeCorpus;
pub use self::wordlist::Wordlist;
pub type CorpusMap = Arc<HashMap<String, Arc<RwLock<CorpusType>>>>;
pub type CorpusIndices = Arc<HashMap<String, AtomicUsize>>;
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Clone, Default, PartialEq, Eq, Hash, PartialOrd, Ord, Debug)]
#[non_exhaustive]
pub enum CorpusItemType {
#[default]
Request,
Data(Data),
LotsOfData(Vec<Data>),
}
pub trait Corpus: Named {
fn add(&mut self, value: Data);
fn get(&self, index: usize) -> Option<&Data>;
#[must_use]
fn items(&self) -> &[Data];
}
#[derive(Clone, Debug, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[non_exhaustive]
pub enum CorpusType {
Wordlist(Wordlist),
Dir(DirCorpus),
Range(RangeCorpus),
HttpMethods(HttpMethodsCorpus),
}
impl Corpus for CorpusType {
#[instrument(skip_all, level = "trace")]
fn add(&mut self, value: Data) {
match self {
Self::Wordlist(corpus) => corpus.add(value),
Self::Dir(corpus) => corpus.add(value),
Self::Range(corpus) => corpus.add(value),
Self::HttpMethods(corpus) => corpus.add(value),
}
}
#[instrument(skip(self), level = "trace")]
fn get(&self, index: usize) -> Option<&Data> {
match self {
Self::Wordlist(corpus) => corpus.get(index),
Self::Dir(corpus) => corpus.get(index),
Self::Range(corpus) => corpus.get(index),
Self::HttpMethods(corpus) => corpus.get(index),
}
}
#[instrument(skip_all, level = "trace")]
fn items(&self) -> &[Data] {
match self {
Self::Wordlist(corpus) => corpus.items(),
Self::Dir(corpus) => corpus.items(),
Self::Range(corpus) => corpus.items(),
Self::HttpMethods(corpus) => corpus.items(),
}
}
}
impl Named for CorpusType {
fn name(&self) -> &str {
match self {
Self::Wordlist(corpus) => corpus.name(),
Self::Dir(corpus) => corpus.name(),
Self::Range(corpus) => corpus.name(),
Self::HttpMethods(corpus) => corpus.name(),
}
}
}
impl Len for CorpusType {
fn len(&self) -> usize {
match self {
Self::Wordlist(corpus) => corpus.len(),
Self::Dir(corpus) => corpus.len(),
Self::Range(corpus) => corpus.len(),
Self::HttpMethods(corpus) => corpus.len(),
}
}
}
impl<'i> IntoIterator for &'i mut CorpusType {
type Item = <&'i mut [Data] as IntoIterator>::Item;
type IntoIter = <&'i mut [Data] as IntoIterator>::IntoIter;
#[inline]
fn into_iter(self) -> Self::IntoIter {
match self {
CorpusType::Wordlist(corpus) => corpus.into_iter(),
CorpusType::Dir(corpus) => corpus.into_iter(),
CorpusType::HttpMethods(corpus) => corpus.into_iter(),
CorpusType::Range(_) => panic!("into_iter not implemented for CorpusType::Range"),
}
}
}
impl IntoIterator for CorpusType {
type Item = <Vec<Data> as IntoIterator>::Item;
type IntoIter = <Vec<Data> as IntoIterator>::IntoIter;
#[inline]
fn into_iter(self) -> Self::IntoIter {
match self {
Self::Wordlist(corpus) => corpus.into_iter(),
Self::Dir(corpus) => corpus.into_iter(),
Self::HttpMethods(corpus) => corpus.into_iter(),
Self::Range(_) => panic!("into_iter not implemented for CorpusType::Range"),
}
}
}
impl<'i> IntoIterator for &'i CorpusType {
type Item = <&'i [Data] as IntoIterator>::Item;
type IntoIter = <&'i [Data] as IntoIterator>::IntoIter;
#[inline]
fn into_iter(self) -> Self::IntoIter {
match self {
CorpusType::Wordlist(corpus) => corpus.into_iter(),
CorpusType::Dir(corpus) => corpus.into_iter(),
CorpusType::HttpMethods(corpus) => corpus.into_iter(),
CorpusType::Range(_) => panic!("into_iter not implemented for CorpusType::Range"),
}
}
}
impl Deref for CorpusType {
type Target = dyn Corpus;
fn deref(&self) -> &Self::Target {
match self {
Self::Wordlist(corpus) => corpus,
Self::Dir(corpus) => corpus,
Self::Range(corpus) => corpus,
Self::HttpMethods(corpus) => corpus,
}
}
}
impl DerefMut for CorpusType {
fn deref_mut(&mut self) -> &mut Self::Target {
match self {
Self::Wordlist(corpus) => corpus,
Self::Dir(corpus) => corpus,
Self::Range(corpus) => corpus,
Self::HttpMethods(corpus) => corpus,
}
}
}
impl Display for CorpusType {
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), fmt::Error> {
match self {
Self::Wordlist(corpus) => corpus.fmt(f),
Self::Dir(corpus) => corpus.fmt(f),
Self::Range(corpus) => corpus.fmt(f),
Self::HttpMethods(corpus) => corpus.fmt(f),
}
}
}
mod typestate {
pub trait CorpusBuildState {}
pub struct NoItems;
pub struct NoName;
pub struct NotUnique;
pub struct HasItems;
pub struct HasName;
pub struct Unique;
impl CorpusBuildState for NoItems {}
impl CorpusBuildState for NoName {}
impl CorpusBuildState for NotUnique {}
impl CorpusBuildState for HasItems {}
impl CorpusBuildState for HasName {}
impl CorpusBuildState for Unique {}
}