awpak_rs/parser/
parser.rs

1use std::collections::HashMap;
2
3use serde_json::Value;
4
5use crate::{from_async_str::FromAsyncStr, from_value::FromValue, io::io::IO};
6
7pub fn serialize_value<T>( value : T ) -> Option<Value>
8where T: serde::Serialize
9{
10    match serde_json::to_value( value ) {
11        Ok( v ) => Some( v ),
12        _ => None
13    }
14}
15
16pub fn parse_value<T>( io : &IO, from : &str ) -> Option<T>
17where T: for<'a> serde::Deserialize<'a> + FromValue
18{
19    match from
20    {
21        "request_body" => parse_value_from_request_body( io ),
22        "query_params" => parse_value_from_query_params( io ),
23        _ => None
24    }
25}
26
27pub fn parse_body_param_value<T>( io : &IO, name : &str ) -> Option<T>
28where T: for<'a> serde::Deserialize<'a> + FromValue
29{
30    match io.request.body.get_param( name ) {
31        Some( v ) => T::from_value( v ),
32        _ => None
33    }
34}
35
36pub fn parse_from_value<T>( value : &Value ) -> Option<T>
37where T: for<'a> serde::Deserialize<'a>
38{
39    match serde_json::from_value( value.clone() )
40    {
41        Ok( v ) => Some( v ),
42        _ => match value {
43            serde_json::Value::String( v ) => match serde_json::from_str( v )
44            {
45                Ok( v ) => Some( v ),
46                _ => None
47            },
48            _ => None
49        }
50    }
51}
52
53fn parse_value_from_request_body<T>( io : &IO ) -> Option<T>
54where T: for<'a> serde::Deserialize<'a> + FromValue
55{
56    match io.request.body.value.as_ref()
57    {
58        Some( v ) => T::from_value( v ),
59        _ => None
60    }
61}
62
63pub fn parse_query_param_value<T>( io : &IO, name : &str ) -> Option<T>
64where T: for<'a> serde::Deserialize<'a> + FromValue
65{
66    match &io.request.uri.query_map
67    {
68        Some( v ) => match v.get( name )
69        {
70            Some( s ) => match &serde_json::from_str( s )
71            {
72                Ok( v ) => T::from_value( v ),
73                _ => match serde_json::to_value( s )
74                {
75                    Ok( v ) => T::from_value( &v ),
76                    _ => None    
77                }
78            },
79            _ => T::from_value( &serde_json::Value::Null )    
80        },
81        _ => T::from_value( &serde_json::Value::Null )   
82    }
83}
84
85fn parse_value_from_query_params<T>( io : &IO ) -> Option<T>
86where T: for<'a> serde::Deserialize<'a>
87{
88    let query_params = &io.request.uri.query;
89
90    if query_params.is_none()
91    {
92        let salida : Result<T, _> = serde_qs::from_str( "" );
93
94        if salida.is_err()
95        {
96            return None;
97        }
98
99        return Some( salida.unwrap() );
100    }
101
102    let salida : Result<T, _> = serde_qs::from_str( query_params.as_ref().unwrap() );
103
104    if salida.is_err()
105    {
106        //TODO: Hacer que el query_map sea un HashMap<String, Value>. Habrá que revisar la función parse_query_param_value
107        if io.request.uri.query_map.is_none()
108        {
109            return None;
110        }
111
112        let mut map : HashMap<String, serde_json::Value> = HashMap::new();
113
114        for item in io.request.uri.query_map.as_ref().unwrap()
115        {
116            let val = match serde_json::from_str::<serde_json::Value>( item.1 )
117            {
118                Ok( v ) => Ok( v ),
119                _ => match serde_json::to_value( item.1 ) {
120                    Ok( v ) => Ok( v ),
121                    _ => Err( () )
122                }
123            };
124
125            if val.is_ok()
126            {
127                map.insert( item.0.clone(), val.unwrap() );
128            }
129        }
130
131        let value = serde_json::to_value( map );
132
133        if value.is_err()
134        {
135            return None;
136        }
137
138        let salida : Result<T, _> = serde_json::from_value( value.unwrap() );
139
140        if salida.is_err()
141        {
142            return None;
143        }
144
145        return Some( salida.unwrap() )
146    }
147
148    Some( salida.unwrap() )
149}
150
151pub async fn parse_path_variable<T>( io : &IO, ind : usize ) -> Option<T>
152where T: FromAsyncStr<T>
153{
154    match io.request.uri.path.split( "/" ).enumerate().find(  | v | v.0 == ind ).map( | v | v.1 )
155    {
156        Some( v ) => match T::from_async_str( io, v ).await
157        {
158            Ok( v ) => Some( v ),
159            _ => None
160        },
161        _ => None
162    }
163}
164
165#[cfg(test)]
166mod tests {
167    use crate::io::response::response_data::ResponseData;
168
169    use super::*;
170
171    #[test]
172    fn test_parse_query_param_value()
173    {
174        let io = IO::with_response( ResponseData::default() );
175
176        let val  = parse_query_param_value::<Option<String>>( &io, "a" );
177
178        assert!( val.is_some() );
179
180        let val = val.unwrap();
181
182        assert!( val.is_none() );
183    }
184}