pub( crate ) mod private
{
use crate::string::split::*;
use crate::string::isolate::isolate_right;
use std::collections::HashMap;
#[ derive( Debug, Clone, PartialEq, Eq ) ]
pub enum OpType<T>
{
Primitive( T ),
Vector( Vec<T> ),
Map( HashMap<String, T> ),
}
impl<T : Default> Default for OpType<T>
{
fn default() -> Self
{
OpType::Primitive( T::default() )
}
}
impl<T> From<T> for OpType<T>
{
fn from( value: T ) -> Self
{
OpType::Primitive( value )
}
}
impl<T> From<Vec<T>> for OpType<T>
{
fn from( value: Vec<T> ) -> Self
{
OpType::Vector( value )
}
}
impl<T> Into<Vec<T>> for OpType<T>
{
fn into( self ) -> Vec<T>
{
match self
{
OpType::Vector( vec ) => vec,
_ => unimplemented!( "not implemented" ),
}
}
}
impl<T : Clone> OpType<T>
{
pub fn append( mut self, item : OpType<T> ) -> OpType<T>
{
let mut mut_item = item;
match self
{
OpType::Primitive( value ) =>
{
match mut_item
{
OpType::Primitive( ins ) =>
{
let vector = vec![ value, ins ];
OpType::Vector( vector )
}
OpType::Vector( ref mut vector ) =>
{
vector.insert( 0, value );
mut_item
},
OpType::Map( _ ) => panic!( "Unexpected operation. Please, use method `insert` to insert item in hash map." ),
}
},
OpType::Vector( ref mut vector ) =>
{
match mut_item
{
OpType::Primitive( ins ) =>
{
vector.push( ins );
self
}
OpType::Vector( ref mut ins_vec ) =>
{
vector.append( ins_vec );
self
},
OpType::Map( _ ) => panic!( "Unexpected operation. Please, use method `insert` to insert item in hash map." ),
}
},
OpType::Map( _ ) => panic!( "Unexpected operation. Please, use method `insert` to insert item in hash map." ),
}
}
pub fn primitive( self ) -> Option<T>
{
match self
{
OpType::Primitive( v ) => Some( v ),
_ => None,
}
}
pub fn vector( self ) -> Option<Vec<T>>
{
match self
{
OpType::Vector( vec ) => Some( vec ),
_ => None,
}
}
}
#[ allow( dead_code ) ]
#[ derive( Debug, Default, PartialEq, Eq ) ]
pub struct Request< 'a >
{
pub original : &'a str,
pub key_val_delimeter : &'a str,
pub commands_delimeter : &'a str,
pub subject : String,
pub subjects : Vec<String>,
pub map : HashMap<String, OpType<String>>,
pub maps : Vec<HashMap<String, OpType<String>>>,
}
#[ derive( Debug, former::Former ) ]
#[ perform( fn parse( mut self ) -> Request< 'a > ) ]
pub struct ParseOptions< 'a >
{
#[ default( "" ) ]
src : &'a str,
#[ default( ":" ) ]
key_val_delimeter : &'a str,
#[ default( ";" ) ]
commands_delimeter : &'a str,
#[ default( true ) ]
quoting : bool,
#[ default( true ) ]
unquoting : bool,
#[ default( true ) ]
parsing_arrays : bool,
#[ default( false ) ]
several_values : bool,
#[ default( false ) ]
subject_win_paths_maybe : bool,
}
pub trait ParseOptionsAdapter< 'a >
{
fn src( &self ) -> &'a str;
fn key_val_delimeter( &self ) -> &'a str;
fn commands_delimeter( &self ) -> &'a str;
fn quoting( &self ) -> bool;
fn unquoting( &self ) -> bool;
fn parsing_arrays( &self ) -> bool;
fn several_values( &self ) -> bool;
fn subject_win_paths_maybe( &self ) -> bool;
fn parse( self ) -> Request< 'a >
where
Self : Sized,
{
Request::default()
}
}
impl< 'a > ParseOptionsAdapter< 'a > for ParseOptions< 'a >
{
fn src( &self ) -> &'a str
{
self.src
}
fn key_val_delimeter( &self ) -> &'a str
{
self.key_val_delimeter
}
fn commands_delimeter( &self ) -> &'a str
{
self.commands_delimeter
}
fn quoting( &self ) -> bool
{
self.quoting
}
fn unquoting( &self ) -> bool
{
self.unquoting
}
fn parsing_arrays( &self ) -> bool
{
self.parsing_arrays
}
fn several_values( &self ) -> bool
{
self.several_values
}
fn subject_win_paths_maybe( &self ) -> bool
{
self.subject_win_paths_maybe
}
fn parse( mut self ) -> Request< 'a >
where
Self : Sized,
{
let mut result = Request
{
original : self.src(),
key_val_delimeter : self.key_val_delimeter(),
commands_delimeter : self.commands_delimeter(),
..Default::default()
};
self.src = self.src.trim();
if self.src.is_empty()
{
return result;
}
let commands =
if self.commands_delimeter.trim().is_empty()
{
vec![ self.src().to_string() ]
}
else
{
let iter = split()
.src( self.src() )
.delimeter( self.commands_delimeter() )
.quoting( self.quoting() )
.stripping( true )
.preserving_empty( false )
.preserving_delimeters( false )
.perform();
iter.map( String::from ).collect::< Vec< _ > >()
};
for command in commands
{
let mut map_entries;
if self.key_val_delimeter.trim().is_empty()
{
map_entries = ( command.as_str(), None, "" );
}
else
{
map_entries = match command.split_once( self.key_val_delimeter )
{
Some( entries ) => ( entries.0, Some( self.key_val_delimeter ), entries.1 ),
None => ( command.as_str(), None, "" ),
};
}
let subject;
let mut map : HashMap<String, OpType<String>> = HashMap::new();
if map_entries.1.is_some()
{
let subject_and_key = isolate_right()
.src( map_entries.0.trim() )
.delimeter( " " )
.none( false )
.perform();
subject = subject_and_key.0;
map_entries.0 = subject_and_key.2;
let mut join = String::from( map_entries.0 );
join.push_str( map_entries.1.unwrap() );
join.push_str( map_entries.2 );
let mut splits = split()
.src( join.as_str() )
.delimeter( self.key_val_delimeter )
.stripping( false )
.quoting( self.quoting )
.preserving_empty( true )
.preserving_delimeters( true )
.preserving_quoting( true )
.perform()
.map( String::from ).collect::< Vec< _ > >();
let mut pairs = vec![];
for a in ( 0..splits.len() - 2 ).step_by( 2 )
{
let mut right = splits[ a + 2 ].clone();
while a < ( splits.len() - 3 )
{
let cuts = isolate_right()
.src( right.trim() )
.delimeter( " " )
.none( false )
.perform();
if cuts.1.is_none()
{
let mut joined = splits[ a + 2 ].clone();
joined.push_str( splits[ a + 3 ].as_str() );
joined.push_str( splits[ a + 4 ].as_str() );
splits[ a + 2 ] = joined;
right = splits[ a + 2 ].clone();
splits.remove( a + 3 );
splits.remove( a + 4 );
continue;
}
splits[ a + 2 ] = cuts.2.to_string();
right = cuts.0.to_string();
break;
}
let left = splits[ a ].clone();
let right = right.trim().to_string();
if self.unquoting
{
if left.contains( '\"' ) || left.contains( '\'' ) || right.contains( '\"' ) || right.contains( '\'' )
{
unimplemented!( "not implemented" );
}
}
pairs.push( left );
pairs.push( right );
}
let str_to_vec_maybe = | src : &str | -> Option<Vec<String>>
{
if !src.starts_with( '[' ) || !src.ends_with( ']' )
{
return None;
}
let splits = split()
.src( &src[ 1..src.len() - 1 ] )
.delimeter( "," )
.stripping( true )
.quoting( self.quoting )
.preserving_empty( false )
.preserving_delimeters( false )
.preserving_quoting( false )
.perform()
.map( | e | String::from( e ).trim().to_owned() ).collect::< Vec<String> >();
Some( splits )
};
for a in ( 0..pairs.len() - 1 ).step_by( 2 )
{
let left = &pairs[ a ];
let right_str = &pairs[ a + 1 ];
let mut right = OpType::Primitive( pairs[ a + 1 ].to_string() );
if self.parsing_arrays
{
if let Some( vector ) = str_to_vec_maybe( right_str )
{
right = OpType::Vector( vector );
}
}
if self.several_values
{
if let Some( op ) = map.get( left )
{
let value = op.clone().append( right );
map.insert( left.to_string(), value );
}
else
{
map.insert( left.to_string(), right );
}
}
else
{
map.insert( left.to_string(), right );
}
}
}
else
{
subject = map_entries.0;
}
if self.unquoting
{
if subject.contains( '\"' ) || subject.contains( '\'' )
{
unimplemented!( "not implemented" );
}
}
if self.subject_win_paths_maybe
{
unimplemented!( "not implemented" );
}
result.subjects.push( subject.to_string() );
result.maps.push( map );
}
if !result.subjects.is_empty()
{
result.subject = result.subjects[ 0 ].clone();
}
if !result.maps.is_empty()
{
result.map = result.maps[ 0 ].clone();
}
result
}
}
pub fn request_parse<'a>() -> ParseOptionsFormer<'a>
{
ParseOptions::former()
}
}
#[ doc( inline ) ]
#[ allow( unused_imports ) ]
pub use protected::*;
pub mod protected
{
#[ allow( unused_imports ) ]
pub use super::orphan::*;
pub use super::private::
{
OpType,
Request,
ParseOptions,
ParseOptionsAdapter,
request_parse,
};
}
pub mod orphan
{
pub use super::exposed::*;
}
pub mod exposed
{
pub use super::private::
{
ParseOptionsAdapter,
request_parse,
};
}
pub mod prelude
{
pub use super::private::ParseOptionsAdapter;
}