aboutsummaryrefslogtreecommitdiff
path: root/azalea-brigadier/src/context/command_context.rs
blob: 0139f7e98c93cf1c760a78a8338531d650e043ff (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
use std::{
    any::Any,
    collections::HashMap,
    fmt::{self, Debug},
    rc::Rc,
    sync::Arc,
};

use parking_lot::RwLock;

use super::{ParsedArgument, parsed_command_node::ParsedCommandNode, string_range::StringRange};
use crate::{
    modifier::RedirectModifier,
    tree::{Command, CommandNode},
};

/// A built `CommandContextBuilder`.
pub struct CommandContext<S, R = i32> {
    pub source: Arc<S>,
    pub(super) input: String,
    pub(super) arguments: HashMap<String, ParsedArgument>,
    pub(super) command: Command<S, R>,
    pub(super) root_node: Arc<RwLock<CommandNode<S, R>>>,
    pub(super) nodes: Vec<ParsedCommandNode<S, R>>,
    pub(super) range: StringRange,
    pub(super) child: Option<Rc<CommandContext<S, R>>>,
    pub(super) modifier: Option<Arc<RedirectModifier<S, R>>>,
    pub(super) forks: bool,
}

impl<S, R> Clone for CommandContext<S, R> {
    fn clone(&self) -> Self {
        Self {
            source: self.source.clone(),
            input: self.input.clone(),
            arguments: self.arguments.clone(),
            command: self.command.clone(),
            root_node: self.root_node.clone(),
            nodes: self.nodes.clone(),
            range: self.range,
            child: self.child.clone(),
            modifier: self.modifier.clone(),
            forks: self.forks,
        }
    }
}

impl<S, R> Debug for CommandContext<S, R> {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.debug_struct("CommandContext")
            // .field("source", &self.source)
            .field("input", &self.input)
            // .field("arguments", &self.arguments)
            // .field("command", &self.command)
            // .field("root_node", &self.root_node)
            // .field("nodes", &self.nodes)
            .field("range", &self.range)
            .field("child", &self.child)
            // .field("modifier", &self.modifier)
            .field("forks", &self.forks)
            .finish()
    }
}

impl<S, R> CommandContext<S, R> {
    pub fn copy_for(&self, source: Arc<S>) -> Self {
        if Arc::ptr_eq(&source, &self.source) {
            // fast path
            return self.clone();
        }

        CommandContext {
            source,
            input: self.input.clone(),
            arguments: self.arguments.clone(),
            command: self.command.clone(),
            root_node: self.root_node.clone(),
            nodes: self.nodes.clone(),
            range: self.range,
            child: self.child.clone(),
            modifier: self.modifier.clone(),
            forks: self.forks,
        }
    }

    pub fn child(&self) -> Option<&CommandContext<S, R>> {
        self.child.as_ref().map(|c| c.as_ref())
    }

    pub fn last_child(&self) -> &CommandContext<S, R> {
        let mut result = self;
        while let Some(child) = result.child() {
            result = child;
        }
        result
    }

    pub fn command(&self) -> &Command<S, R> {
        &self.command
    }

    pub fn argument(&self, name: &str) -> Option<&dyn Any> {
        let argument = self.arguments.get(name);
        argument.map(|a| a.result.as_ref())
    }

    pub fn redirect_modifier(&self) -> Option<&RedirectModifier<S, R>> {
        self.modifier.as_ref().map(|m| m.as_ref())
    }

    pub fn range(&self) -> &StringRange {
        &self.range
    }

    pub fn input(&self) -> &str {
        &self.input
    }

    pub fn root_node(&self) -> &Arc<RwLock<CommandNode<S, R>>> {
        &self.root_node
    }

    pub fn nodes(&self) -> &[ParsedCommandNode<S, R>] {
        &self.nodes
    }

    pub fn has_nodes(&self) -> bool {
        !self.nodes.is_empty()
    }

    pub fn is_forked(&self) -> bool {
        self.forks
    }
}