macros.rs 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105
  1. #[macro_export]
  2. macro_rules! dispatcher {
  3. {
  4. $($command:ident {
  5. $handler:ident,
  6. [$($tag:tt)+],
  7. },)+$(,)?
  8. }=> {
  9. $(
  10. #[allow(non_snake_case, non_camel_case_types)]
  11. pub mod $command {
  12. use super::*;
  13. pub struct Command {
  14. pub tags: &'static [&'static str],
  15. }
  16. impl Command {
  17. pub fn new() -> Self {
  18. Self {
  19. tags: &[$($tag,)+],
  20. }
  21. }
  22. }
  23. impl ExecutableCommand for Command {
  24. fn execute(&self, args: &[Value]) -> Result<Value, String> {
  25. $handler(args)
  26. }
  27. fn name(&self) -> &'static str {
  28. stringify!($command)
  29. }
  30. }
  31. }
  32. )+
  33. use std::ops::Deref;
  34. pub trait ExecutableCommand {
  35. fn execute(&self, args: &[Value]) -> Result<Value, String>;
  36. fn name(&self) -> &'static str;
  37. }
  38. #[allow(non_snake_case, non_camel_case_types)]
  39. pub enum Dispatcher {
  40. $(
  41. $command($command::Command),
  42. )+
  43. }
  44. impl Dispatcher {
  45. pub fn new(command: &Value) -> Result<Self, String> {
  46. let command = match command {
  47. Value::String(x) => Ok(x.as_str()),
  48. Value::Blob(x) => Ok(unsafe { std::str::from_utf8_unchecked(&x) }),
  49. _ => Err("Invalid type"),
  50. }?;
  51. match command.to_lowercase().as_str() {
  52. $(
  53. stringify!($command) => Ok(Self::$command($command::Command::new())),
  54. )+
  55. _ => Err(format!("Command ({}) not found", command)),
  56. }
  57. }
  58. }
  59. impl Deref for Dispatcher {
  60. type Target = dyn ExecutableCommand + Sync + Send;
  61. fn deref(&self) -> &(dyn ExecutableCommand + Sync + Send + 'static) {
  62. match self {
  63. $(
  64. Self::$command(v) => v as &(dyn ExecutableCommand + Sync + Send),
  65. )+
  66. }
  67. }
  68. }
  69. }
  70. }
  71. #[macro_export]
  72. macro_rules! value_try_from {
  73. {$type: ty, $value: expr} => {
  74. impl From<$type> for Value {
  75. fn from(value: $type) -> Value {
  76. $value(value.into())
  77. }
  78. }
  79. value_vec_try_from!($type);
  80. }
  81. }
  82. #[macro_export]
  83. macro_rules! value_vec_try_from {
  84. {$type: ty} => {
  85. impl From<Vec<$type>> for Value {
  86. fn from(value: Vec<$type>) -> Value {
  87. Value::Array(value.iter().map(|x| (*x).into()).collect())
  88. }
  89. }
  90. }
  91. }