use crate::error::DecodeError;
use super::callbacks::DecodeDecoder;
use super::shared::{Charset, Delimiter, Duplicates};
#[derive(Clone, Debug)]
pub struct DecodeOptions {
pub(crate) allow_dots: bool,
pub(crate) decode_dot_in_keys: bool,
pub(crate) allow_empty_lists: bool,
pub(crate) allow_sparse_lists: bool,
pub(crate) list_limit: usize,
pub(crate) charset: Charset,
pub(crate) charset_sentinel: bool,
pub(crate) comma: bool,
pub(crate) delimiter: Delimiter,
pub(crate) depth: usize,
pub(crate) parameter_limit: usize,
pub(crate) duplicates: Duplicates,
pub(crate) ignore_query_prefix: bool,
pub(crate) interpret_numeric_entities: bool,
pub(crate) parse_lists: bool,
pub(crate) strict_depth: bool,
pub(crate) strict_null_handling: bool,
pub(crate) throw_on_limit_exceeded: bool,
pub(crate) decoder: Option<DecodeDecoder>,
}
impl Default for DecodeOptions {
fn default() -> Self {
Self {
allow_dots: false,
decode_dot_in_keys: false,
allow_empty_lists: false,
allow_sparse_lists: false,
list_limit: 20,
charset: Charset::Utf8,
charset_sentinel: false,
comma: false,
delimiter: Delimiter::default(),
depth: 5,
parameter_limit: 1000,
duplicates: Duplicates::Combine,
ignore_query_prefix: false,
interpret_numeric_entities: false,
parse_lists: true,
strict_depth: false,
strict_null_handling: false,
throw_on_limit_exceeded: false,
decoder: None,
}
}
}
impl DecodeOptions {
pub fn new() -> Self {
Self::default()
}
pub fn allow_dots(&self) -> bool {
self.allow_dots
}
pub fn with_allow_dots(mut self, allow_dots: bool) -> Self {
self.allow_dots = allow_dots;
if !allow_dots {
self.decode_dot_in_keys = false;
}
self
}
pub fn decode_dot_in_keys(&self) -> bool {
self.decode_dot_in_keys
}
pub fn with_decode_dot_in_keys(mut self, decode_dot_in_keys: bool) -> Self {
self.decode_dot_in_keys = decode_dot_in_keys;
if decode_dot_in_keys {
self.allow_dots = true;
}
self
}
pub fn allow_empty_lists(&self) -> bool {
self.allow_empty_lists
}
pub fn with_allow_empty_lists(mut self, allow_empty_lists: bool) -> Self {
self.allow_empty_lists = allow_empty_lists;
self
}
pub fn allow_sparse_lists(&self) -> bool {
self.allow_sparse_lists
}
pub fn with_allow_sparse_lists(mut self, allow_sparse_lists: bool) -> Self {
self.allow_sparse_lists = allow_sparse_lists;
self
}
pub fn list_limit(&self) -> usize {
self.list_limit
}
pub fn with_list_limit(mut self, list_limit: usize) -> Self {
self.list_limit = list_limit;
self
}
pub fn charset(&self) -> Charset {
self.charset
}
pub fn with_charset(mut self, charset: Charset) -> Self {
self.charset = charset;
self
}
pub fn charset_sentinel(&self) -> bool {
self.charset_sentinel
}
pub fn with_charset_sentinel(mut self, charset_sentinel: bool) -> Self {
self.charset_sentinel = charset_sentinel;
self
}
pub fn comma(&self) -> bool {
self.comma
}
pub fn with_comma(mut self, comma: bool) -> Self {
self.comma = comma;
self
}
pub fn delimiter(&self) -> &Delimiter {
&self.delimiter
}
pub fn with_delimiter(mut self, delimiter: Delimiter) -> Self {
self.delimiter = delimiter;
self
}
pub fn depth(&self) -> usize {
self.depth
}
pub fn with_depth(mut self, depth: usize) -> Self {
self.depth = depth;
self
}
pub fn parameter_limit(&self) -> usize {
self.parameter_limit
}
pub fn with_parameter_limit(mut self, parameter_limit: usize) -> Self {
self.parameter_limit = parameter_limit;
self
}
pub fn duplicates(&self) -> Duplicates {
self.duplicates
}
pub fn with_duplicates(mut self, duplicates: Duplicates) -> Self {
self.duplicates = duplicates;
self
}
pub fn ignore_query_prefix(&self) -> bool {
self.ignore_query_prefix
}
pub fn with_ignore_query_prefix(mut self, ignore_query_prefix: bool) -> Self {
self.ignore_query_prefix = ignore_query_prefix;
self
}
pub fn interpret_numeric_entities(&self) -> bool {
self.interpret_numeric_entities
}
pub fn with_interpret_numeric_entities(mut self, interpret_numeric_entities: bool) -> Self {
self.interpret_numeric_entities = interpret_numeric_entities;
self
}
pub fn parse_lists(&self) -> bool {
self.parse_lists
}
pub fn with_parse_lists(mut self, parse_lists: bool) -> Self {
self.parse_lists = parse_lists;
self
}
pub fn strict_depth(&self) -> bool {
self.strict_depth
}
pub fn with_strict_depth(mut self, strict_depth: bool) -> Self {
self.strict_depth = strict_depth;
self
}
pub fn strict_null_handling(&self) -> bool {
self.strict_null_handling
}
pub fn with_strict_null_handling(mut self, strict_null_handling: bool) -> Self {
self.strict_null_handling = strict_null_handling;
self
}
pub fn throw_on_limit_exceeded(&self) -> bool {
self.throw_on_limit_exceeded
}
pub fn with_throw_on_limit_exceeded(mut self, throw_on_limit_exceeded: bool) -> Self {
self.throw_on_limit_exceeded = throw_on_limit_exceeded;
self
}
pub fn decoder(&self) -> Option<&DecodeDecoder> {
self.decoder.as_ref()
}
pub fn with_decoder(mut self, decoder: Option<DecodeDecoder>) -> Self {
self.decoder = decoder;
self
}
pub(crate) fn validate(&self) -> Result<(), DecodeError> {
if self.parameter_limit == 0 {
return Err(DecodeError::InvalidParameterLimit);
}
if self.decode_dot_in_keys && !self.allow_dots {
return Err(DecodeError::DecodeDotInKeysRequiresAllowDots);
}
if matches!(&self.delimiter, Delimiter::String(text) if text.is_empty()) {
return Err(DecodeError::EmptyDelimiter);
}
Ok(())
}
}