use std::borrow::Cow;
use std::collections::HashMap;
use bytes::Bytes;
use crate::http::request::DynamicBodyMapTrait;
#[derive(Debug)]
pub struct XWWWFormUrlEncoded<'a> {
data:HashMap<&'a[u8],&'a[u8]>
}
#[derive(Debug)]
pub struct HeapXWWWFormUrlEncoded{
data:HashMap<String,Bytes>
}
impl HeapXWWWFormUrlEncoded {
pub fn new(data:&XWWWFormUrlEncoded)->Self{
let all = data.all();
Self {
data:all
}
}
pub fn all_ref(&self)->&HashMap<String,Bytes>{
&self.data
}
}
impl DynamicBodyMapTrait for HeapXWWWFormUrlEncoded {
fn get_as_bytes(&self, key: &str) -> Option<&[u8]> {
if let Some(data) = self.data.get(key){
return Some(data.as_ref())
}
None
}
fn get(&self, key: &str) -> Option<Cow<'_,str>> {
if let Some(data) = self.data.get(key){
return Some(String::from_utf8_lossy(data.as_ref()))
}
None
}
fn all(&self) -> HashMap<String, Bytes> {
self.data.clone()
}
}
impl<'a> DynamicBodyMapTrait for XWWWFormUrlEncoded<'a> {
fn get_as_bytes(&self, key: &str) -> Option<&[u8]> {
self.get_as_bytes_ref(key)
}
fn get(&self, key: &str) -> Option<Cow<'_,str>> {
self.get_as_str(key)
}
fn all(&self) -> HashMap<String, Bytes> {
let mut map = HashMap::new();
for (key,value) in &self.data {
map.insert(String::from_utf8_lossy(key).to_string(),Bytes::copy_from_slice(value));
}
map
}
}
impl <'a> XWWWFormUrlEncoded<'a> {
fn get_as_bytes_ref(&self,key:&str)->Option<&'a[u8]>{
if let Some(data) = self.data.get(key.as_bytes()) {
return Some(*data)
}
None
}
fn get_as_str(&self,key:&str)->Option<Cow<'_,str>>{
if let Some(data) = self.get_as_bytes(key) {
return String::from_utf8_lossy(data).into();
}
None
}
pub fn all_ref(&self)->&HashMap<&'a[u8],&'a[u8]>{
&self.data
}
pub (crate) fn new(payload:&'a[u8])->XWWWFormUrlEncoded<'a>{
let mut map = HashMap::new();
let mut key : Option<&'a [u8]> = None;
let mut cursor = 0_usize;
for (index,byte) in payload.iter().enumerate() {
match key {
None => {
match byte {
b'=' => {
key = Some(&payload[cursor..index]);
cursor = index +1;
}
_=>{}
}
}
Some(k) => {
match byte {
b'&' | b'\r' => {
map.insert(k,&payload[cursor..index]);
cursor=index+1;
key = None;
}
_=>{}
}
}
}
}
if let Some(k) = key {
map.insert(k,&payload[cursor..]);
}
return XWWWFormUrlEncoded{ data:map}
}
}
#[cfg(test)]
mod test {
use super::XWWWFormUrlEncoded;
#[test]
fn test_xxx_form_url_encoded() {
let p1 = b"username=john&age=25¬e=ok";
let parsed = XWWWFormUrlEncoded::new(p1);
assert_eq!(parsed.data.get(b"username".as_ref()), Some(&b"john".as_ref()));
assert_eq!(parsed.data.get(b"age".as_ref()), Some(&b"25".as_ref()));
assert_eq!(parsed.data.get(b"note".as_ref()), Some(&b"ok".as_ref()));
}
}