sift_query_core/protocol/raw/
mod.rs1use crate::{ParamError, QueryLimits};
3use sift_query_algorithm::BoundedCounter;
4use url::{decode_component, encode_component, encoded_len};
5mod url;
6
7#[derive(Debug, Clone, Default, PartialEq, Eq)]
9pub struct RawParams {
10 entries: Vec<(String, String)>,
11 raw_bytes: usize,
12 decoded_bytes: usize,
13}
14
15impl RawParams {
16 pub fn parse(query: &str) -> Result<Self, ParamError> {
17 Self::parse_with_limits(query, &QueryLimits::default())
18 }
19
20 pub fn parse_with_limits(query: &str, limits: &QueryLimits) -> Result<Self, ParamError> {
21 if query.len() > limits.max_raw_query_bytes {
22 return Err(ParamError::QueryTooLong);
23 }
24 if query.is_empty() {
25 return Ok(Self::default());
26 }
27
28 let mut entries = Vec::new();
29 let mut decoded_bytes = BoundedCounter::new(limits.max_decoded_bytes);
30 for item in query.split('&') {
31 if entries.len() >= limits.max_raw_items {
32 return Err(ParamError::TooComplex("raw parameter item count"));
33 }
34 if item.is_empty() {
35 return Err(ParamError::InvalidName(String::new()));
36 }
37 let (raw_key, raw_value) = item.split_once('=').unwrap_or((item, ""));
38 let key = decode_component(raw_key)?;
39 let value = decode_component(raw_value)?;
40 if key.is_empty() || key.len() > limits.max_key_bytes {
41 return Err(ParamError::InvalidName(key));
42 }
43 if value.len() > limits.max_value_bytes {
44 return Err(ParamError::TooComplex("single parameter value length"));
45 }
46 decoded_bytes
47 .try_add(key.len())
48 .and_then(|()| decoded_bytes.try_add(value.len()))
49 .map_err(|_| ParamError::TooComplex("decoded parameter bytes"))?;
50 entries.push((key, value));
51 }
52 Ok(Self {
53 entries,
54 raw_bytes: query.len(),
55 decoded_bytes: decoded_bytes.used(),
56 })
57 }
58
59 pub fn from_entries(
62 entries: impl IntoIterator<Item = (String, String)>,
63 limits: &QueryLimits,
64 ) -> Result<Self, ParamError> {
65 let mut output = Vec::new();
66 let mut decoded_bytes = BoundedCounter::new(limits.max_decoded_bytes);
67 let mut raw_bytes = 0usize;
68 for (key, value) in entries {
69 if output.len() >= limits.max_raw_items {
70 return Err(ParamError::TooComplex("filtered parameter item count"));
71 }
72 if key.is_empty() || key.len() > limits.max_key_bytes {
73 return Err(ParamError::InvalidName(key.clone()));
74 }
75 if value.len() > limits.max_value_bytes {
76 return Err(ParamError::TooComplex("filtered parameter value length"));
77 }
78 decoded_bytes
79 .try_add(key.len())
80 .and_then(|()| decoded_bytes.try_add(value.len()))
81 .map_err(|_| ParamError::TooComplex("filtered parameter bytes"))?;
82 raw_bytes = raw_bytes
83 .saturating_add(encoded_len(&key))
84 .saturating_add(encoded_len(&value))
85 .saturating_add(if output.is_empty() { 1 } else { 2 });
86 if raw_bytes > limits.max_raw_query_bytes {
87 return Err(ParamError::QueryTooLong);
88 }
89 output.push((key, value));
90 }
91 Ok(Self {
92 entries: output,
93 raw_bytes,
94 decoded_bytes: decoded_bytes.used(),
95 })
96 }
97
98 #[must_use]
99 pub fn entries(&self) -> &[(String, String)] {
100 &self.entries
101 }
102
103 #[must_use]
105 pub fn to_query_string(&self) -> String {
106 let mut output = String::with_capacity(self.raw_bytes);
107 for (index, (key, value)) in self.entries.iter().enumerate() {
108 if index > 0 {
109 output.push('&');
110 }
111 encode_component(key, &mut output);
112 output.push('=');
113 encode_component(value, &mut output);
114 }
115 output
116 }
117
118 #[must_use]
119 pub fn len(&self) -> usize {
120 self.entries.len()
121 }
122
123 #[must_use]
124 pub fn is_empty(&self) -> bool {
125 self.entries.is_empty()
126 }
127
128 #[must_use]
129 pub const fn raw_bytes(&self) -> usize {
130 self.raw_bytes
131 }
132
133 #[must_use]
134 pub const fn decoded_bytes(&self) -> usize {
135 self.decoded_bytes
136 }
137}