use crate::auth::AccessLevel;
pub mod completion;
pub mod path;
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub enum CommandKind {
Sync,
#[cfg(feature = "async")]
Async,
}
#[derive(Debug, Clone)]
pub struct CommandMeta<L: AccessLevel> {
pub id: &'static str,
pub name: &'static str,
pub description: &'static str,
pub access_level: L,
pub kind: CommandKind,
pub min_args: usize,
pub max_args: usize,
}
#[derive(Debug, Clone)]
pub struct Directory<L: AccessLevel> {
pub name: &'static str,
pub children: &'static [Node<L>],
pub access_level: L,
}
#[derive(Debug, Clone)]
pub enum Node<L: AccessLevel> {
Command(&'static CommandMeta<L>),
Directory(&'static Directory<L>),
}
impl<L: AccessLevel> Node<L> {
pub fn is_command(&self) -> bool {
matches!(self, Node::Command(_))
}
pub fn is_directory(&self) -> bool {
matches!(self, Node::Directory(_))
}
pub fn name(&self) -> &'static str {
match self {
Node::Command(cmd) => cmd.name,
Node::Directory(dir) => dir.name,
}
}
pub fn access_level(&self) -> L {
match self {
Node::Command(cmd) => cmd.access_level,
Node::Directory(dir) => dir.access_level,
}
}
}
impl<L: AccessLevel> Directory<L> {
pub fn find_child(&self, name: &str) -> Option<&Node<L>> {
self.children.iter().find(|child| child.name() == name)
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::auth::AccessLevel;
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
enum TestAccessLevel {
Guest = 0,
User = 1,
}
impl AccessLevel for TestAccessLevel {
fn from_str(s: &str) -> Option<Self> {
match s {
"Guest" => Some(Self::Guest),
"User" => Some(Self::User),
_ => None,
}
}
fn as_str(&self) -> &'static str {
match self {
Self::Guest => "Guest",
Self::User => "User",
}
}
}
#[test]
fn test_command_kind() {
assert_eq!(CommandKind::Sync, CommandKind::Sync);
#[cfg(feature = "async")]
assert_ne!(CommandKind::Sync, CommandKind::Async);
}
#[test]
fn test_node_type_checking() {
const CMD: CommandMeta<TestAccessLevel> = CommandMeta {
id: "test",
name: "test",
description: "Test command",
access_level: TestAccessLevel::User,
kind: CommandKind::Sync,
min_args: 0,
max_args: 0,
};
let node = Node::Command(&CMD);
assert!(node.is_command());
assert!(!node.is_directory());
assert_eq!(node.name(), "test");
}
}