diff --git a/module/move/wca/Cargo.toml b/module/move/wca/Cargo.toml index 2d8184148e..f6f277f90b 100644 --- a/module/move/wca/Cargo.toml +++ b/module/move/wca/Cargo.toml @@ -50,6 +50,7 @@ former = { workspace = true, features = [ "default" ] } log = "0.4" #closure = "0.3" textdistance = { version = "1.0", optional = true } # fuzzy commands search +indexmap = "2.2.6" [dev-dependencies] test_tools = { workspace = true } diff --git a/module/move/wca/src/ca/grammar/command.rs b/module/move/wca/src/ca/grammar/command.rs index 8357eb9a54..38a02583a4 100644 --- a/module/move/wca/src/ca/grammar/command.rs +++ b/module/move/wca/src/ca/grammar/command.rs @@ -2,7 +2,8 @@ pub( crate ) mod private { use crate::*; - use std::collections::{ BTreeMap, HashMap }; + use std::collections::{ HashMap }; + use indexmap::IndexMap; use former::{ Former, StoragePreform }; use wtools::Itertools; @@ -98,10 +99,7 @@ pub( crate ) mod private #[ subform_entry( setter = true ) ] pub subjects : Vec< ValueDescription >, /// Hints and types for command options. - pub properties : BTreeMap< CommandName, ValueDescription >, - /// Last inserted property id. - #[ scalar( setter = false ) ] - last_id : usize, + pub properties : IndexMap< String, ValueDescription >, /// Map of aliases. // Aliased key -> Original key pub properties_aliases : HashMap< String, String >, @@ -122,11 +120,11 @@ pub( crate ) mod private { Order::Nature => { - self.properties.iter().map( | ( key, value ) | ( &key.name, value ) ).collect() + self.properties.iter().map( | ( key, value ) | ( key, value ) ).collect() } Order::Lexicography => { - self.properties.iter().map( | ( key, value ) | ( &key.name, value ) ).sorted_by_key( | ( k, _ ) | *k ).collect() + self.properties.iter().map( | ( key, value ) | ( key, value ) ).sorted_by_key( | ( k, _ ) | *k ).collect() } } } @@ -228,9 +226,7 @@ pub( crate ) mod private optional : property.optional, }; debug_assert!( !properties.contains_key( &property.name ), "Property name `{}` is already used for `{:?}`", property.name, properties[ &property.name ] ); - super_former.storage.last_id = Some( super_former.storage.last_id.unwrap_or_default() + 1 ); - let name = CommandName { id : super_former.storage.last_id.unwrap(), name : property.name.clone() }; - properties.insert( name, value ); + properties.insert( property.name.clone(), value ); let mut aliases = super_former.storage.properties_aliases.unwrap_or_default(); debug_assert!( !aliases.contains_key( &property.name ), "Name `{}` is already used for `{}` as alias", property.name, aliases[ &property.name ] ); diff --git a/module/move/wca/src/ca/grammar/dictionary.rs b/module/move/wca/src/ca/grammar/dictionary.rs index 5e213dcbf4..06c8479f8b 100644 --- a/module/move/wca/src/ca/grammar/dictionary.rs +++ b/module/move/wca/src/ca/grammar/dictionary.rs @@ -2,9 +2,8 @@ pub( crate ) mod private { use crate::*; use former::Former; + use indexmap::IndexMap; use wtools::Itertools; - use std::cmp::Ordering; - use std::collections::BTreeMap; // qqq : `Former` does not handle this situation well @@ -14,55 +13,6 @@ pub( crate ) mod private // #[ derive( Debug, Former ) ] // pub struct Dictionary( HashMap< String, Command > ); - /// Command name with id. - #[ derive( Debug, Default, Clone, Eq ) ] - pub struct CommandName - { - /// id of command. - pub( crate ) id : usize, - /// Name of command. - pub name : String, - } - - impl std::borrow::Borrow< String > for CommandName - { - fn borrow( &self ) -> &String - { - &self.name - } - } - - impl Ord for CommandName - { - fn cmp( &self, other : &Self ) -> Ordering - { - if self.name == other.name - { - Ordering::Equal - } - else - { - self.id.cmp( &other.id ) - } - } - } - - impl PartialEq< Self > for CommandName - { - fn eq( &self, other : &Self ) -> bool - { - self.name.eq( &other.name ) - } - } - - impl PartialOrd for CommandName - { - fn partial_cmp( &self, other : &Self ) -> Option< Ordering > - { - self.id.partial_cmp( &other.id ) - } - } - /// A collection of commands. /// /// This structure holds a btreemap of commands where each command is mapped to its name. @@ -70,9 +20,8 @@ pub( crate ) mod private pub struct Dictionary { #[ scalar( setter = false ) ] - pub( crate ) commands : BTreeMap< CommandName, Command >, + pub( crate ) commands : IndexMap< String, Command >, #[ scalar( setter = false ) ] - dictionary_last_id : usize, pub( crate ) order : Order, } @@ -83,11 +32,8 @@ pub( crate ) mod private pub fn command( mut self, command : Command ) -> Self { let mut commands = self.storage.commands.unwrap_or_default(); - self.storage.dictionary_last_id = Some( self.storage.dictionary_last_id.unwrap_or_default() + 1 ); - let name = CommandName { id : self.storage.dictionary_last_id.unwrap(), name : command.phrase.clone() }; - commands.insert( name, command ); + commands.insert( command.phrase.clone(), command ); self.storage.commands = Some( commands ); - self } } @@ -101,9 +47,7 @@ pub( crate ) mod private /// * `command` - The command to be registered. pub fn register( &mut self, command : Command ) -> Option< Command > { - self.dictionary_last_id += 1; - let name = CommandName { id : self.dictionary_last_id, name : command.phrase.clone() }; - self.commands.insert( name, command ) + self.commands.insert( command.phrase.clone(), command ) } /// Retrieves the command with the specified `name` from the `commands` hashmap. @@ -118,9 +62,10 @@ pub( crate ) mod private /// Returns `None` if no command with the specified `name` is found. pub fn command< Name >( &self, name : &Name ) -> Option< &Command > where - Name : std::hash::Hash + Eq + Ord + ToString, + String : std::borrow::Borrow< Name >, + Name : std::hash::Hash + Eq, { - self.commands.iter().find( | ( k, _ ) | k.name == name.to_string() ).map( | ( _, v ) | v ) + self.commands.get( name ) } /// Find commands that match a given name part. @@ -149,11 +94,11 @@ pub( crate ) mod private { Order::Nature => { - self.commands.iter().map( | ( key, value ) | ( &key.name, value ) ).collect() + self.commands.iter().map( | ( key, value ) | ( key, value ) ).collect() } Order::Lexicography => { - self.commands.iter().map( | ( key, value ) | ( &key.name, value ) ).sorted_by_key( | ( key, _ ) | *key ).collect() + self.commands.iter().map( | ( key, value ) | ( key, value ) ).sorted_by_key( | ( key, _ ) | *key ).collect() } } } @@ -165,5 +110,4 @@ pub( crate ) mod private crate::mod_interface! { exposed use Dictionary; - exposed use CommandName; } diff --git a/module/move/wca/src/ca/verifier/verifier.rs b/module/move/wca/src/ca/verifier/verifier.rs index 8fe25073d3..b443000f7d 100644 --- a/module/move/wca/src/ca/verifier/verifier.rs +++ b/module/move/wca/src/ca/verifier/verifier.rs @@ -4,7 +4,8 @@ pub( crate ) mod private use ca::grammar::command::ValueDescription; // use former::Former; - use std::collections::{ BTreeMap, HashMap }; + use std::collections::HashMap; + use indexmap::IndexMap; use wtools::{ error, error::Result, err }; use ca::help::private::{ HelpGeneratorOptions, LevelOfDetail, generate_help_content }; @@ -63,7 +64,7 @@ pub( crate ) mod private let sim = dictionary .commands .iter() - .map( |( name, c )| ( jaro.for_str( name.name.as_str(), user_input ).nsim(), c ) ) + .map( |( name, c )| ( jaro.for_str( name.as_str(), user_input ).nsim(), c ) ) .max_by( |( s1, _ ), ( s2, _ )| s1.total_cmp( s2 ) ); if let Some(( sim, variant )) = sim { @@ -79,7 +80,7 @@ pub( crate ) mod private fn get_count_from_properties ( - properties : &BTreeMap< CommandName, ValueDescription >, + properties : &IndexMap< String, ValueDescription >, properties_aliases : &HashMap< String, String >, raw_properties : &HashMap< String, String > ) -> usize