non_std 0.1.4

Collection of general purpose tools for solving problems. Fundamentally extend the language without spoiling, so may be used solely or in conjunction with another module of such kind.
Documentation

pub use wtools::error::*;
use std::collections::HashMap;

///
/// Instruction.
///

#[ derive( Debug, PartialEq ) ]
pub struct Instruction
{
  /// Error of parsing an instruction.
  pub err : Option< BasicError >,
  /// Command name.
  pub command_name : Box< str >,
  /// Subject of command.
  pub subject : Vec< Box< str > >,
  /// Properties of command.
  pub properties_map : HashMap< Box< str >, Box< str > >,
}

impl Instruction
{
  fn new() -> Self
  {
    Self
    {
      err : None,
      command_name : Default::default(),
      subject : Default::default(),
      properties_map : Default::default(),

    }
  }
}

//

///
/// Adapter for instruction.
///

pub trait InstructionParseParamsAdapter
{

  /// Print info about command format.
  fn about_command_format( &self ) -> &'static str
  {
r#"Command should start from a dot `.`.
Command can have a subject and properties.
Property is pair delimited by colon `:`.
For example: `.struct1 subject key1:val key2:val2`."#
  }

  /// Check that command begins with dot.
  fn instruction_split_is_command< Src : AsRef< str > >( &self, src : Src ) -> bool
  {
    src.as_ref().starts_with( "." )
  }

  /// Normalize command name.
  fn command_name_normalize< Src : AsRef< str > >( &self, src : Src ) -> Box< str >
  {
    let splits : Vec< &str > = src.as_ref()
    .split_whitespace()
    .flat_map( | e | e.split( "." ) )
    .filter( | e | e != &"" )
    .collect();
    ( ".".to_string() + &splits.join( "." ) ).to_string().into_boxed_str()
  }

  /// Make properties map.
  fn split_belong_to_properties< Src : AsRef< str > >( &self, src : Src ) -> i32
  {
    let src = src.as_ref();
    if !src.contains( ':' )
    {
      return 0;
    }
    let splits : Vec< &str > = src
    .split_ascii_whitespace()
    .flat_map( | e | e.split( ":" ) )
    .filter( | e | e != &"" )
    .collect();
    let index = splits.iter().position( | e | *e == ":" ).unwrap();
    if index == 0
    {
      return 2;
    }
    return 1;
  }

  /// Parse instruction from splits.
  /* zzz : make it accept also vector */
  fn parse_from_splits< I >( &self, mut splits : I ) -> Instruction
  where
    < I as Iterator >::Item : core::fmt::Display,
    < I as Iterator >::Item : AsRef< str >,
    I : core::iter::Iterator,
  {
    let mut result = Instruction::new();

    // splits.for_each( | arg | println!( "{}", arg ) );

    let command_name = splits.next();

    if command_name.is_none()
    {
      result.err = Some( err!( "Lack of arguments" ) );
      return result;
    }

    let command_name = command_name.unwrap();

    if !self.instruction_split_is_command( &command_name )
    {
      result.err = Some( err!( "{}\nDoes not start as command\n{}", command_name, self.about_command_format() ) );
      return result;
    }

    result.command_name = self.command_name_normalize( command_name );

    // let params_splits;

    while let Some( split ) = splits.next()
    {
      let split_unwrap = split.as_ref();
      let belong = self.split_belong_to_properties( split_unwrap );
      if belong > 0
      {
        // if belong == 1
        {
          let props_splits = std::iter::once( split ).chain( splits );
          result.properties_map = super::props::parse_from_splits( props_splits );
        }
        break;
      }
      result.subject.push( split_unwrap.to_string().into_boxed_str() );
      // params_splits.chain();
    }

    // dbg!(  );

    // super::params::parse_from_splits(  );

    result
  }

//   //
//
//   fn str_structure_parse()
//   {
//
//   }

}

///
/// Parameters of instruction.
///

#[ derive( Debug, PartialEq ) ]
pub struct InstructionParseParams
{
}

impl InstructionParseParams
{
  /// Create new instruction parameters.
  pub fn new() -> Self
  {
    Self
    {
    }
  }
}

impl InstructionParseParamsAdapter for InstructionParseParams
{
}

//

///
/// Parse input as instruction from splits.
///

pub fn parse_from_splits< I >( splits : I ) -> Instruction
where
  < I as Iterator >::Item : core::fmt::Display,
  < I as Iterator >::Item : AsRef< str >,
  I : core::iter::Iterator,
{
  let params = InstructionParseParams::new();
  let instruction = params.parse_from_splits( splits );
  instruction
}

//

// var command = commandIdentitySet.command = Object.create( null );
// command.subjectHint = 'A name of identity.';
// command.hint = 'Modify an existed identity.';
// command.longHint = 'Much longer description.';
// command.properties =
// {
//   'login' : 'An identity login ( user name ) that is used for all identity scripts if no specifique login defined.',
//   'email' : 'An email that is used for all identity scripts if no specifique email defined.',
// };