use std::{collections::BTreeSet, fmt::Display};
use super::script_result::PsValue;
#[derive(Debug, Clone, PartialEq)]
pub struct MethodToken {
token: String,
self_: PsValue,
name: String,
arguments: Vec<PsValue>,
}
impl MethodToken {
pub fn new(token: String, self_: PsValue, name: String, arguments: Vec<PsValue>) -> Self {
Self {
token,
self_,
name,
arguments,
}
}
pub fn token(&self) -> &String {
&self.token
}
pub fn name(&self) -> &String {
&self.name
}
pub fn self_(&self) -> &PsValue {
&self.self_
}
pub fn args(&self) -> &Vec<PsValue> {
&self.arguments
}
}
#[derive(Debug, Clone, PartialEq)]
pub struct CommandToken {
token: String,
name: String,
arguments: Vec<String>,
}
impl CommandToken {
pub fn new(token: String, name: String, arguments: Vec<String>) -> Self {
Self {
token,
name,
arguments,
}
}
pub fn token(&self) -> &String {
&self.token
}
pub fn name(&self) -> &String {
&self.name
}
pub fn args(&self) -> &Vec<String> {
&self.arguments
}
}
#[derive(Debug, Clone, PartialEq)]
pub struct ExpressionToken {
token: String,
value: PsValue,
}
impl ExpressionToken {
pub fn new(token: String, value: PsValue) -> Self {
Self { token, value }
}
}
#[derive(Debug, Clone, PartialEq)]
pub struct StringExpandableToken {
token: String,
value: String,
}
impl StringExpandableToken {
pub fn new(token: String, value: String) -> Self {
Self { token, value }
}
pub fn token(&self) -> &String {
&self.token
}
pub fn value(&self) -> &String {
&self.value
}
}
#[derive(Debug, Clone, PartialEq)]
pub struct TypeToken {
pub name: String,
}
impl TypeToken {
pub fn new(name: String) -> Self {
Self { name }
}
pub fn name(&self) -> &String {
&self.name
}
}
#[derive(Debug, Clone, PartialEq)]
pub enum Token {
StringExpandable(StringExpandableToken),
String(String),
Expression(ExpressionToken),
Method(MethodToken),
Command(CommandToken),
Type(TypeToken),
}
impl Token {
pub fn method(token: String, self_: PsValue, name: String, arguments: Vec<PsValue>) -> Self {
Token::Method(MethodToken {
token,
self_,
name,
arguments,
})
}
pub fn command(token: String, name: String, arguments: Vec<String>) -> Self {
Token::Command(CommandToken {
token,
name,
arguments,
})
}
pub fn expression(token: String, value: PsValue) -> Self {
Token::Expression(ExpressionToken { token, value })
}
pub fn string_expandable(token: String, value: String) -> Self {
Token::StringExpandable(StringExpandableToken { token, value })
}
pub fn type_literal(name: String) -> Self {
Token::Type(TypeToken { name })
}
}
impl Display for Token {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{:?}", self)
}
}
#[derive(Default, Debug, Clone, PartialEq)]
pub struct Tokens(Vec<Token>);
impl Tokens {
pub fn new() -> Self {
Self(Vec::new())
}
pub fn push(&mut self, token: Token) {
self.0.push(token)
}
pub fn all(&self) -> Vec<Token> {
self.0.clone()
}
pub fn literal_strings(&self) -> Vec<String> {
self.0
.iter()
.filter_map(|token| match token {
Token::String(literal) => Some(literal.clone()),
_ => None,
})
.collect()
}
pub fn string_set(&self) -> BTreeSet<String> {
let mut string_set = BTreeSet::new();
for token in self.0.iter() {
match token {
Token::String(deobfuscated)
| Token::StringExpandable(StringExpandableToken {
value: deobfuscated,
..
}) => {
let _ = string_set.insert(deobfuscated.to_string());
}
_ => {}
}
}
string_set
}
pub fn lowercased_string_set(&self) -> BTreeSet<String> {
let mut string_set = BTreeSet::new();
for token in self.0.iter() {
match token {
Token::String(deobfuscated)
| Token::StringExpandable(StringExpandableToken {
value: deobfuscated,
..
}) => {
let _ = string_set.insert(deobfuscated.to_ascii_lowercase());
}
_ => {}
}
}
string_set
}
pub fn expandable_strings(&self) -> Vec<StringExpandableToken> {
self.0
.iter()
.filter_map(|token| match token {
Token::StringExpandable(expandable) => Some(expandable.clone()),
_ => None,
})
.collect()
}
pub fn expressions(&self) -> Vec<ExpressionToken> {
self.0
.iter()
.filter_map(|token| match token {
Token::Expression(expr) => Some(expr.clone()),
_ => None,
})
.collect()
}
pub fn methods(&self) -> Vec<MethodToken> {
self.0
.iter()
.filter_map(|token| match token {
Token::Method(method) => Some(method.clone()),
_ => None,
})
.collect()
}
pub fn commands(&self) -> Vec<CommandToken> {
self.0
.iter()
.filter_map(|token| match token {
Token::Command(command) => Some(command.clone()),
_ => None,
})
.collect()
}
pub fn methods_and_commands(&self) -> BTreeSet<&str> {
self.0
.iter()
.filter_map(|token| match token {
Token::Command(command) => Some(command.name().as_str()),
Token::Method(method) => Some(method.name().as_str()),
_ => None,
})
.collect()
}
pub fn ttypes(&self) -> BTreeSet<&str> {
self.0
.iter()
.filter_map(|token| match token {
Token::Type(type_token) => Some(type_token.name().as_str()),
_ => None,
})
.collect()
}
}