Change string type to be passed by reference
This commit is contained in:
parent
525c87bf0f
commit
20e0ec0e3d
@ -43,7 +43,7 @@ impl BuiltInValue {
|
|||||||
fn get(&self) -> &Value {
|
fn get(&self) -> &Value {
|
||||||
match self {
|
match self {
|
||||||
BuiltInValue::Args => ARGS.get_or_init(|| {
|
BuiltInValue::Args => ARGS.get_or_init(|| {
|
||||||
let args = args().map(|arg| Value::String(arg.to_string())).collect();
|
let args = args().map(|arg| Value::string(arg.to_string())).collect();
|
||||||
|
|
||||||
Value::List(List::with_items(args))
|
Value::List(List::with_items(args))
|
||||||
}),
|
}),
|
||||||
|
@ -72,7 +72,7 @@ impl AbstractTree for Index {
|
|||||||
let key = value.as_string()?;
|
let key = value.as_string()?;
|
||||||
|
|
||||||
map.variables()?
|
map.variables()?
|
||||||
.get(key)
|
.get(key.as_str())
|
||||||
.map(|(value, _)| value.clone())
|
.map(|(value, _)| value.clone())
|
||||||
.unwrap_or_default()
|
.unwrap_or_default()
|
||||||
};
|
};
|
||||||
@ -81,9 +81,9 @@ impl AbstractTree for Index {
|
|||||||
}
|
}
|
||||||
Value::String(string) => {
|
Value::String(string) => {
|
||||||
let index = self.index.run(source, context)?.as_integer()? as usize;
|
let index = self.index.run(source, context)?.as_integer()? as usize;
|
||||||
let item = string.chars().nth(index).unwrap_or_default();
|
let item = string.read()?.chars().nth(index).unwrap_or_default();
|
||||||
|
|
||||||
Ok(Value::String(item.to_string()))
|
Ok(Value::string(item.to_string()))
|
||||||
}
|
}
|
||||||
_ => Err(Error::ExpectedCollection { actual: collection }),
|
_ => Err(Error::ExpectedCollection { actual: collection }),
|
||||||
}
|
}
|
||||||
|
@ -128,7 +128,7 @@ impl AbstractTree for ValueNode {
|
|||||||
ValueNode::Float(value_source) => Value::Float(value_source.parse().unwrap()),
|
ValueNode::Float(value_source) => Value::Float(value_source.parse().unwrap()),
|
||||||
ValueNode::Function(function) => Value::Function(function.clone()),
|
ValueNode::Function(function) => Value::Function(function.clone()),
|
||||||
ValueNode::Integer(value_source) => Value::Integer(value_source.parse().unwrap()),
|
ValueNode::Integer(value_source) => Value::Integer(value_source.parse().unwrap()),
|
||||||
ValueNode::String(value_source) => Value::String(value_source.parse().unwrap()),
|
ValueNode::String(value_source) => Value::string(value_source.clone()),
|
||||||
ValueNode::List(expressions) => {
|
ValueNode::List(expressions) => {
|
||||||
let mut values = Vec::with_capacity(expressions.len());
|
let mut values = Vec::with_capacity(expressions.len());
|
||||||
|
|
||||||
|
@ -187,7 +187,7 @@ fn display_value(value: &Value, ui: &mut egui::Ui) {
|
|||||||
ui.label(function.to_string());
|
ui.label(function.to_string());
|
||||||
}
|
}
|
||||||
Value::String(string) => {
|
Value::String(string) => {
|
||||||
ui.label(RichText::new(string).color(Color32::GREEN));
|
ui.label(RichText::new(string.read().unwrap().as_str()).color(Color32::GREEN));
|
||||||
}
|
}
|
||||||
Value::Float(float) => {
|
Value::Float(float) => {
|
||||||
ui.label(float.to_string());
|
ui.label(float.to_string());
|
||||||
|
@ -68,9 +68,9 @@ impl BuiltInFunction {
|
|||||||
Error::expect_argument_amount(self.name(), 1, arguments.len())?;
|
Error::expect_argument_amount(self.name(), 1, arguments.len())?;
|
||||||
|
|
||||||
let path = arguments.first().unwrap().as_string()?;
|
let path = arguments.first().unwrap().as_string()?;
|
||||||
let file_content = read_to_string(path)?;
|
let file_content = read_to_string(path.as_str())?;
|
||||||
|
|
||||||
Ok(Value::String(file_content))
|
Ok(Value::string(file_content))
|
||||||
}
|
}
|
||||||
BuiltInFunction::JsonParse => {
|
BuiltInFunction::JsonParse => {
|
||||||
Error::expect_argument_amount(self.name(), 1, arguments.len())?;
|
Error::expect_argument_amount(self.name(), 1, arguments.len())?;
|
||||||
@ -88,8 +88,8 @@ impl BuiltInFunction {
|
|||||||
list.items().len()
|
list.items().len()
|
||||||
} else if let Ok(map) = value.as_map() {
|
} else if let Ok(map) = value.as_map() {
|
||||||
map.variables()?.len()
|
map.variables()?.len()
|
||||||
} else if let Ok(string) = value.as_string() {
|
} else if let Ok(str) = value.as_string() {
|
||||||
string.chars().count()
|
str.chars().count()
|
||||||
} else {
|
} else {
|
||||||
return Err(Error::ExpectedCollection {
|
return Err(Error::ExpectedCollection {
|
||||||
actual: value.clone(),
|
actual: value.clone(),
|
||||||
|
@ -12,10 +12,17 @@ pub enum StringFunction {
|
|||||||
AsBytes,
|
AsBytes,
|
||||||
EndsWith,
|
EndsWith,
|
||||||
Find,
|
Find,
|
||||||
|
Insert,
|
||||||
IsAscii,
|
IsAscii,
|
||||||
IsEmpty,
|
IsEmpty,
|
||||||
Lines,
|
Lines,
|
||||||
Matches,
|
Matches,
|
||||||
|
Parse,
|
||||||
|
Pop,
|
||||||
|
Push,
|
||||||
|
Remove,
|
||||||
|
ReplaceRange,
|
||||||
|
Retain,
|
||||||
Split,
|
Split,
|
||||||
SplitAt,
|
SplitAt,
|
||||||
SplitInclusive,
|
SplitInclusive,
|
||||||
@ -33,6 +40,7 @@ pub enum StringFunction {
|
|||||||
TrimMatches,
|
TrimMatches,
|
||||||
TrimStart,
|
TrimStart,
|
||||||
TrimStartMatches,
|
TrimStartMatches,
|
||||||
|
Truncate,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl StringFunction {
|
impl StringFunction {
|
||||||
@ -41,10 +49,17 @@ impl StringFunction {
|
|||||||
StringFunction::AsBytes => "as_bytes",
|
StringFunction::AsBytes => "as_bytes",
|
||||||
StringFunction::EndsWith => "ends_with",
|
StringFunction::EndsWith => "ends_with",
|
||||||
StringFunction::Find => "find",
|
StringFunction::Find => "find",
|
||||||
|
StringFunction::Insert => "insert",
|
||||||
StringFunction::IsAscii => "is_ascii",
|
StringFunction::IsAscii => "is_ascii",
|
||||||
StringFunction::IsEmpty => "is_empty",
|
StringFunction::IsEmpty => "is_empty",
|
||||||
StringFunction::Lines => "lines",
|
StringFunction::Lines => "lines",
|
||||||
StringFunction::Matches => "matches",
|
StringFunction::Matches => "matches",
|
||||||
|
StringFunction::Parse => "parse",
|
||||||
|
StringFunction::Pop => "pop",
|
||||||
|
StringFunction::Push => "push",
|
||||||
|
StringFunction::Remove => "remove",
|
||||||
|
StringFunction::ReplaceRange => "replace_range",
|
||||||
|
StringFunction::Retain => "retain",
|
||||||
StringFunction::Split => "split",
|
StringFunction::Split => "split",
|
||||||
StringFunction::SplitAt => "split_at",
|
StringFunction::SplitAt => "split_at",
|
||||||
StringFunction::SplitInclusive => "split_inclusive",
|
StringFunction::SplitInclusive => "split_inclusive",
|
||||||
@ -62,6 +77,7 @@ impl StringFunction {
|
|||||||
StringFunction::TrimMatches => "trim_matches",
|
StringFunction::TrimMatches => "trim_matches",
|
||||||
StringFunction::TrimStart => "trim_start",
|
StringFunction::TrimStart => "trim_start",
|
||||||
StringFunction::TrimStartMatches => "trim_start_matches",
|
StringFunction::TrimStartMatches => "trim_start_matches",
|
||||||
|
StringFunction::Truncate => "truncate",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -77,12 +93,33 @@ impl StringFunction {
|
|||||||
vec![Type::String, Type::String],
|
vec![Type::String, Type::String],
|
||||||
Type::option(Type::Integer),
|
Type::option(Type::Integer),
|
||||||
),
|
),
|
||||||
|
StringFunction::Insert => {
|
||||||
|
Type::function(vec![Type::String, Type::Integer, Type::String], Type::None)
|
||||||
|
}
|
||||||
StringFunction::IsAscii => Type::function(vec![Type::String], Type::Boolean),
|
StringFunction::IsAscii => Type::function(vec![Type::String], Type::Boolean),
|
||||||
StringFunction::IsEmpty => Type::function(vec![Type::String], Type::Boolean),
|
StringFunction::IsEmpty => Type::function(vec![Type::String], Type::Boolean),
|
||||||
StringFunction::Lines => Type::function(vec![Type::String], Type::list(Type::String)),
|
StringFunction::Lines => Type::function(vec![Type::String], Type::list(Type::String)),
|
||||||
StringFunction::Matches => {
|
StringFunction::Matches => {
|
||||||
Type::function(vec![Type::String, Type::String], Type::list(Type::String))
|
Type::function(vec![Type::String, Type::String], Type::list(Type::String))
|
||||||
}
|
}
|
||||||
|
StringFunction::Parse => Type::function(vec![Type::String], Type::Any),
|
||||||
|
StringFunction::Pop => Type::function(vec![], Type::option(Type::String)),
|
||||||
|
StringFunction::Push => Type::function(vec![Type::String], Type::None),
|
||||||
|
StringFunction::Remove => Type::function(
|
||||||
|
vec![Type::String, Type::Integer],
|
||||||
|
Type::option(Type::String),
|
||||||
|
),
|
||||||
|
StringFunction::ReplaceRange => Type::function(
|
||||||
|
vec![Type::String, Type::list(Type::Integer), Type::String],
|
||||||
|
Type::None,
|
||||||
|
),
|
||||||
|
StringFunction::Retain => Type::function(
|
||||||
|
vec![
|
||||||
|
Type::String,
|
||||||
|
Type::function(vec![Type::String], Type::Boolean),
|
||||||
|
],
|
||||||
|
Type::None,
|
||||||
|
),
|
||||||
StringFunction::Split => {
|
StringFunction::Split => {
|
||||||
Type::function(vec![Type::String, Type::String], Type::list(Type::String))
|
Type::function(vec![Type::String, Type::String], Type::list(Type::String))
|
||||||
}
|
}
|
||||||
@ -113,6 +150,9 @@ impl StringFunction {
|
|||||||
}
|
}
|
||||||
StringFunction::ToLowercase => Type::function(vec![Type::String], Type::String),
|
StringFunction::ToLowercase => Type::function(vec![Type::String], Type::String),
|
||||||
StringFunction::ToUppercase => Type::function(vec![Type::String], Type::String),
|
StringFunction::ToUppercase => Type::function(vec![Type::String], Type::String),
|
||||||
|
StringFunction::Truncate => {
|
||||||
|
Type::function(vec![Type::String, Type::Integer], Type::None)
|
||||||
|
}
|
||||||
StringFunction::Trim => Type::function(vec![Type::String], Type::String),
|
StringFunction::Trim => Type::function(vec![Type::String], Type::String),
|
||||||
StringFunction::TrimEnd => Type::function(vec![Type::String], Type::String),
|
StringFunction::TrimEnd => Type::function(vec![Type::String], Type::String),
|
||||||
StringFunction::TrimEndMatches => {
|
StringFunction::TrimEndMatches => {
|
||||||
@ -145,7 +185,8 @@ impl StringFunction {
|
|||||||
Error::expect_argument_amount(self.name(), 2, arguments.len())?;
|
Error::expect_argument_amount(self.name(), 2, arguments.len())?;
|
||||||
|
|
||||||
let string = arguments.get(0).unwrap().as_string()?;
|
let string = arguments.get(0).unwrap().as_string()?;
|
||||||
let pattern = arguments.get(1).unwrap().as_string()?;
|
let pattern_string = arguments.get(1).unwrap().as_string()?;
|
||||||
|
let pattern = pattern_string.as_str();
|
||||||
|
|
||||||
Value::Boolean(string.ends_with(pattern))
|
Value::Boolean(string.ends_with(pattern))
|
||||||
}
|
}
|
||||||
@ -153,7 +194,8 @@ impl StringFunction {
|
|||||||
Error::expect_argument_amount(self.name(), 2, arguments.len())?;
|
Error::expect_argument_amount(self.name(), 2, arguments.len())?;
|
||||||
|
|
||||||
let string = arguments.get(0).unwrap().as_string()?;
|
let string = arguments.get(0).unwrap().as_string()?;
|
||||||
let pattern = arguments.get(1).unwrap().as_string()?;
|
let pattern_string = arguments.get(1).unwrap().as_string()?;
|
||||||
|
let pattern = pattern_string.as_str();
|
||||||
let find = string
|
let find = string
|
||||||
.find(pattern)
|
.find(pattern)
|
||||||
.map(|index| Box::new(Value::Integer(index as i64)));
|
.map(|index| Box::new(Value::Integer(index as i64)));
|
||||||
@ -174,13 +216,24 @@ impl StringFunction {
|
|||||||
|
|
||||||
Value::Boolean(string.is_empty())
|
Value::Boolean(string.is_empty())
|
||||||
}
|
}
|
||||||
|
StringFunction::Insert => {
|
||||||
|
Error::expect_argument_amount(self.name(), 3, arguments.len())?;
|
||||||
|
|
||||||
|
let mut string = arguments.get(0).unwrap().as_string()?.to_string();
|
||||||
|
let index = arguments.get(1).unwrap().as_integer()? as usize;
|
||||||
|
let insertion = arguments.get(2).unwrap().as_string()?;
|
||||||
|
|
||||||
|
string.insert_str(index, &insertion);
|
||||||
|
|
||||||
|
Value::none()
|
||||||
|
}
|
||||||
StringFunction::Lines => {
|
StringFunction::Lines => {
|
||||||
Error::expect_argument_amount(self.name(), 1, arguments.len())?;
|
Error::expect_argument_amount(self.name(), 1, arguments.len())?;
|
||||||
|
|
||||||
let string = arguments.first().unwrap().as_string()?;
|
let string = arguments.first().unwrap().as_string()?;
|
||||||
let lines = string
|
let lines = string
|
||||||
.lines()
|
.lines()
|
||||||
.map(|line| Value::String(line.to_string()))
|
.map(|line| Value::string(line.to_string()))
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
Value::List(List::with_items(lines))
|
Value::List(List::with_items(lines))
|
||||||
@ -189,22 +242,58 @@ impl StringFunction {
|
|||||||
Error::expect_argument_amount(self.name(), 2, arguments.len())?;
|
Error::expect_argument_amount(self.name(), 2, arguments.len())?;
|
||||||
|
|
||||||
let string = arguments.get(0).unwrap().as_string()?;
|
let string = arguments.get(0).unwrap().as_string()?;
|
||||||
let pattern = arguments.get(1).unwrap().as_string()?;
|
let pattern_string = arguments.get(1).unwrap().as_string()?;
|
||||||
|
let pattern = pattern_string.as_str();
|
||||||
let matches = string
|
let matches = string
|
||||||
.matches(pattern)
|
.matches(pattern)
|
||||||
.map(|pattern| Value::String(pattern.to_string()))
|
.map(|pattern| Value::string(pattern.to_string()))
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
Value::List(List::with_items(matches))
|
Value::List(List::with_items(matches))
|
||||||
}
|
}
|
||||||
|
StringFunction::Parse => {
|
||||||
|
Error::expect_argument_amount(self.name(), 1, arguments.len())?;
|
||||||
|
|
||||||
|
let string = arguments.first().unwrap().as_string()?;
|
||||||
|
|
||||||
|
if let Ok(integer) = string.parse::<i64>() {
|
||||||
|
Value::option(Some(Value::Integer(integer)))
|
||||||
|
} else if let Ok(float) = string.parse::<f64>() {
|
||||||
|
Value::option(Some(Value::Float(float)))
|
||||||
|
} else {
|
||||||
|
Value::none()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
StringFunction::Pop => {
|
||||||
|
Error::expect_argument_amount(self.name(), 1, arguments.len())?;
|
||||||
|
|
||||||
|
let mut string = arguments.first().unwrap().as_string_mut()?;
|
||||||
|
let popped = string.pop().map(|char| Value::string(char.to_string()));
|
||||||
|
|
||||||
|
Value::option(popped)
|
||||||
|
}
|
||||||
|
StringFunction::Push => {
|
||||||
|
Error::expect_argument_amount(self.name(), 2, arguments.len())?;
|
||||||
|
|
||||||
|
let mut string = arguments.get(0).unwrap().as_string_mut()?;
|
||||||
|
let addition = arguments.get(1).unwrap().as_string()?;
|
||||||
|
|
||||||
|
string.push_str(&addition);
|
||||||
|
|
||||||
|
Value::none()
|
||||||
|
}
|
||||||
|
StringFunction::Remove => todo!(),
|
||||||
|
StringFunction::ReplaceRange => todo!(),
|
||||||
|
StringFunction::Retain => todo!(),
|
||||||
StringFunction::Split => {
|
StringFunction::Split => {
|
||||||
Error::expect_argument_amount(self.name(), 2, arguments.len())?;
|
Error::expect_argument_amount(self.name(), 2, arguments.len())?;
|
||||||
|
|
||||||
let string = arguments.get(0).unwrap().as_string()?;
|
let string = arguments.get(0).unwrap().as_string()?;
|
||||||
let pattern = arguments.get(1).unwrap().as_string()?;
|
let pattern_string = arguments.get(1).unwrap().as_string()?;
|
||||||
|
let pattern = pattern_string.as_str();
|
||||||
let sections = string
|
let sections = string
|
||||||
.split(pattern)
|
.split(pattern)
|
||||||
.map(|section| Value::String(section.to_string()))
|
.map(|section| Value::string(section.to_string()))
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
Value::List(List::with_items(sections))
|
Value::List(List::with_items(sections))
|
||||||
@ -217,18 +306,19 @@ impl StringFunction {
|
|||||||
let (left, right) = string.split_at(index as usize);
|
let (left, right) = string.split_at(index as usize);
|
||||||
|
|
||||||
Value::List(List::with_items(vec![
|
Value::List(List::with_items(vec![
|
||||||
Value::String(left.to_string()),
|
Value::string(left.to_string()),
|
||||||
Value::String(right.to_string()),
|
Value::string(right.to_string()),
|
||||||
]))
|
]))
|
||||||
}
|
}
|
||||||
StringFunction::SplitInclusive => {
|
StringFunction::SplitInclusive => {
|
||||||
Error::expect_argument_amount(self.name(), 2, arguments.len())?;
|
Error::expect_argument_amount(self.name(), 2, arguments.len())?;
|
||||||
|
|
||||||
let string = arguments.get(0).unwrap().as_string()?;
|
let string = arguments.get(0).unwrap().as_string()?;
|
||||||
let pattern = arguments.get(1).unwrap().as_string()?;
|
let pattern_string = arguments.get(1).unwrap().as_string()?;
|
||||||
|
let pattern = pattern_string.as_str();
|
||||||
let sections = string
|
let sections = string
|
||||||
.split(pattern)
|
.split(pattern)
|
||||||
.map(|pattern| Value::String(pattern.to_string()))
|
.map(|pattern| Value::string(pattern.to_string()))
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
Value::List(List::with_items(sections))
|
Value::List(List::with_items(sections))
|
||||||
@ -238,10 +328,11 @@ impl StringFunction {
|
|||||||
|
|
||||||
let string = arguments.get(0).unwrap().as_string()?;
|
let string = arguments.get(0).unwrap().as_string()?;
|
||||||
let count = arguments.get(1).unwrap().as_integer()?;
|
let count = arguments.get(1).unwrap().as_integer()?;
|
||||||
let pattern = arguments.get(2).unwrap().as_string()?;
|
let pattern_string = arguments.get(2).unwrap().as_string()?;
|
||||||
|
let pattern = pattern_string.as_str();
|
||||||
let sections = string
|
let sections = string
|
||||||
.splitn(count as usize, pattern)
|
.splitn(count as usize, pattern)
|
||||||
.map(|pattern| Value::String(pattern.to_string()))
|
.map(|pattern| Value::string(pattern.to_string()))
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
Value::List(List::with_items(sections))
|
Value::List(List::with_items(sections))
|
||||||
@ -250,11 +341,12 @@ impl StringFunction {
|
|||||||
Error::expect_argument_amount(self.name(), 2, arguments.len())?;
|
Error::expect_argument_amount(self.name(), 2, arguments.len())?;
|
||||||
|
|
||||||
let string = arguments.get(0).unwrap().as_string()?;
|
let string = arguments.get(0).unwrap().as_string()?;
|
||||||
let pattern = arguments.get(1).unwrap().as_string()?;
|
let pattern_string = arguments.get(1).unwrap().as_string()?;
|
||||||
|
let pattern = pattern_string.as_str();
|
||||||
let sections = string.split_once(pattern).map(|(left, right)| {
|
let sections = string.split_once(pattern).map(|(left, right)| {
|
||||||
Value::List(List::with_items(vec![
|
Value::List(List::with_items(vec![
|
||||||
Value::String(left.to_string()),
|
Value::string(left.to_string()),
|
||||||
Value::String(right.to_string()),
|
Value::string(right.to_string()),
|
||||||
]))
|
]))
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -264,10 +356,11 @@ impl StringFunction {
|
|||||||
Error::expect_argument_amount(self.name(), 2, arguments.len())?;
|
Error::expect_argument_amount(self.name(), 2, arguments.len())?;
|
||||||
|
|
||||||
let string = arguments.get(0).unwrap().as_string()?;
|
let string = arguments.get(0).unwrap().as_string()?;
|
||||||
let pattern = arguments.get(1).unwrap().as_string()?;
|
let pattern_string = arguments.get(1).unwrap().as_string()?;
|
||||||
|
let pattern = pattern_string.as_str();
|
||||||
let sections = string
|
let sections = string
|
||||||
.split_terminator(pattern)
|
.split_terminator(pattern)
|
||||||
.map(|section| Value::String(section.to_string()))
|
.map(|section| Value::string(section.to_string()))
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
Value::List(List::with_items(sections))
|
Value::List(List::with_items(sections))
|
||||||
@ -278,7 +371,7 @@ impl StringFunction {
|
|||||||
let string = arguments.get(0).unwrap().as_string()?;
|
let string = arguments.get(0).unwrap().as_string()?;
|
||||||
let sections = string
|
let sections = string
|
||||||
.split_whitespace()
|
.split_whitespace()
|
||||||
.map(|section| Value::String(section.to_string()))
|
.map(|section| Value::string(section.to_string()))
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
Value::List(List::with_items(sections))
|
Value::List(List::with_items(sections))
|
||||||
@ -287,7 +380,8 @@ impl StringFunction {
|
|||||||
Error::expect_argument_amount(self.name(), 2, arguments.len())?;
|
Error::expect_argument_amount(self.name(), 2, arguments.len())?;
|
||||||
|
|
||||||
let string = arguments.get(0).unwrap().as_string()?;
|
let string = arguments.get(0).unwrap().as_string()?;
|
||||||
let pattern = arguments.get(1).unwrap().as_string()?;
|
let pattern_string = arguments.get(1).unwrap().as_string()?;
|
||||||
|
let pattern = pattern_string.as_str();
|
||||||
|
|
||||||
Value::Boolean(string.starts_with(pattern))
|
Value::Boolean(string.starts_with(pattern))
|
||||||
}
|
}
|
||||||
@ -295,10 +389,11 @@ impl StringFunction {
|
|||||||
Error::expect_argument_amount(self.name(), 2, arguments.len())?;
|
Error::expect_argument_amount(self.name(), 2, arguments.len())?;
|
||||||
|
|
||||||
let string = arguments.get(0).unwrap().as_string()?;
|
let string = arguments.get(0).unwrap().as_string()?;
|
||||||
let prefix = arguments.get(1).unwrap().as_string()?;
|
let prefix_string = arguments.get(1).unwrap().as_string()?;
|
||||||
|
let prefix = prefix_string.as_str();
|
||||||
let stripped = string
|
let stripped = string
|
||||||
.strip_prefix(prefix)
|
.strip_prefix(prefix)
|
||||||
.map(|remainder| Value::String(remainder.to_string()));
|
.map(|remainder| Value::string(remainder.to_string()));
|
||||||
|
|
||||||
Value::option(stripped)
|
Value::option(stripped)
|
||||||
}
|
}
|
||||||
@ -308,7 +403,7 @@ impl StringFunction {
|
|||||||
let string = arguments.get(0).unwrap().as_string()?;
|
let string = arguments.get(0).unwrap().as_string()?;
|
||||||
let lowercase = string.to_lowercase();
|
let lowercase = string.to_lowercase();
|
||||||
|
|
||||||
Value::String(lowercase)
|
Value::string(lowercase)
|
||||||
}
|
}
|
||||||
StringFunction::ToUppercase => {
|
StringFunction::ToUppercase => {
|
||||||
Error::expect_argument_amount(self.name(), 1, arguments.len())?;
|
Error::expect_argument_amount(self.name(), 1, arguments.len())?;
|
||||||
@ -316,14 +411,14 @@ impl StringFunction {
|
|||||||
let string = arguments.get(0).unwrap().as_string()?;
|
let string = arguments.get(0).unwrap().as_string()?;
|
||||||
let uppercase = string.to_uppercase();
|
let uppercase = string.to_uppercase();
|
||||||
|
|
||||||
Value::String(uppercase)
|
Value::string(uppercase)
|
||||||
}
|
}
|
||||||
StringFunction::Trim => {
|
StringFunction::Trim => {
|
||||||
Error::expect_argument_amount(self.name(), 1, arguments.len())?;
|
Error::expect_argument_amount(self.name(), 1, arguments.len())?;
|
||||||
|
|
||||||
let trimmed = arguments.first().unwrap().as_string()?.trim().to_string();
|
let trimmed = arguments.first().unwrap().as_string()?.trim().to_string();
|
||||||
|
|
||||||
Value::String(trimmed)
|
Value::string(trimmed)
|
||||||
}
|
}
|
||||||
StringFunction::TrimEnd => {
|
StringFunction::TrimEnd => {
|
||||||
Error::expect_argument_amount(self.name(), 1, arguments.len())?;
|
Error::expect_argument_amount(self.name(), 1, arguments.len())?;
|
||||||
@ -335,16 +430,17 @@ impl StringFunction {
|
|||||||
.trim_end()
|
.trim_end()
|
||||||
.to_string();
|
.to_string();
|
||||||
|
|
||||||
Value::String(trimmed)
|
Value::string(trimmed)
|
||||||
}
|
}
|
||||||
StringFunction::TrimEndMatches => {
|
StringFunction::TrimEndMatches => {
|
||||||
Error::expect_argument_amount(self.name(), 2, arguments.len())?;
|
Error::expect_argument_amount(self.name(), 2, arguments.len())?;
|
||||||
|
|
||||||
let string = arguments.get(0).unwrap().as_string()?;
|
let string = arguments.get(0).unwrap().as_string()?;
|
||||||
let pattern = arguments.get(1).unwrap().as_string()?;
|
let pattern_string = arguments.get(1).unwrap().as_string()?;
|
||||||
|
let pattern = pattern_string.as_str();
|
||||||
let trimmed = string.trim_end_matches(pattern).to_string();
|
let trimmed = string.trim_end_matches(pattern).to_string();
|
||||||
|
|
||||||
Value::String(trimmed)
|
Value::string(trimmed)
|
||||||
}
|
}
|
||||||
StringFunction::TrimMatches => {
|
StringFunction::TrimMatches => {
|
||||||
Error::expect_argument_amount(self.name(), 2, arguments.len())?;
|
Error::expect_argument_amount(self.name(), 2, arguments.len())?;
|
||||||
@ -358,7 +454,7 @@ impl StringFunction {
|
|||||||
.collect::<Vec<char>>();
|
.collect::<Vec<char>>();
|
||||||
let trimmed = string.trim_matches(pattern.as_slice()).to_string();
|
let trimmed = string.trim_matches(pattern.as_slice()).to_string();
|
||||||
|
|
||||||
Value::String(trimmed)
|
Value::string(trimmed)
|
||||||
}
|
}
|
||||||
StringFunction::TrimStart => {
|
StringFunction::TrimStart => {
|
||||||
Error::expect_argument_amount(self.name(), 1, arguments.len())?;
|
Error::expect_argument_amount(self.name(), 1, arguments.len())?;
|
||||||
@ -370,9 +466,10 @@ impl StringFunction {
|
|||||||
.trim_start()
|
.trim_start()
|
||||||
.to_string();
|
.to_string();
|
||||||
|
|
||||||
Value::String(trimmed)
|
Value::string(trimmed)
|
||||||
}
|
}
|
||||||
StringFunction::TrimStartMatches => todo!(),
|
StringFunction::TrimStartMatches => todo!(),
|
||||||
|
StringFunction::Truncate => todo!(),
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(value)
|
Ok(value)
|
||||||
|
@ -57,7 +57,7 @@ fn main() {
|
|||||||
|
|
||||||
if let Some(input) = args.input {
|
if let Some(input) = args.input {
|
||||||
context
|
context
|
||||||
.set("input".to_string(), Value::String(input), None)
|
.set("input".to_string(), Value::string(input), None)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -65,7 +65,7 @@ fn main() {
|
|||||||
let file_contents = read_to_string(path).unwrap();
|
let file_contents = read_to_string(path).unwrap();
|
||||||
|
|
||||||
context
|
context
|
||||||
.set("input".to_string(), Value::String(file_contents), None)
|
.set("input".to_string(), Value::string(file_contents), None)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -16,6 +16,7 @@ use std::{
|
|||||||
fmt::{self, Display, Formatter},
|
fmt::{self, Display, Formatter},
|
||||||
marker::PhantomData,
|
marker::PhantomData,
|
||||||
ops::{Add, AddAssign, Div, Mul, Rem, Sub, SubAssign},
|
ops::{Add, AddAssign, Div, Mul, Rem, Sub, SubAssign},
|
||||||
|
sync::{Arc, RwLock, RwLockReadGuard, RwLockWriteGuard},
|
||||||
};
|
};
|
||||||
|
|
||||||
pub mod function;
|
pub mod function;
|
||||||
@ -32,7 +33,7 @@ pub enum Value {
|
|||||||
List(List),
|
List(List),
|
||||||
Map(Map),
|
Map(Map),
|
||||||
Function(Function),
|
Function(Function),
|
||||||
String(String),
|
String(Arc<RwLock<String>>),
|
||||||
Float(f64),
|
Float(f64),
|
||||||
Integer(i64),
|
Integer(i64),
|
||||||
Boolean(bool),
|
Boolean(bool),
|
||||||
@ -46,6 +47,10 @@ impl Default for Value {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Value {
|
impl Value {
|
||||||
|
pub fn string(string: String) -> Self {
|
||||||
|
Value::String(Arc::new(RwLock::new(string)))
|
||||||
|
}
|
||||||
|
|
||||||
pub fn r#type(&self) -> Type {
|
pub fn r#type(&self) -> Type {
|
||||||
let r#type = match self {
|
let r#type = match self {
|
||||||
Value::List(list) => {
|
Value::List(list) => {
|
||||||
@ -135,10 +140,20 @@ impl Value {
|
|||||||
matches!(self, Value::Map(_))
|
matches!(self, Value::Map(_))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Borrows the value stored in `self` as `String`, or returns `Err` if `self` is not a `Value::String`.
|
/// Borrows the value stored in `self` as `&str`, or returns `Err` if `self` is not a `Value::String`.
|
||||||
pub fn as_string(&self) -> Result<&String> {
|
pub fn as_string(&self) -> Result<RwLockReadGuard<String>> {
|
||||||
match self {
|
match self {
|
||||||
Value::String(string) => Ok(string),
|
Value::String(string) => Ok(string.read()?),
|
||||||
|
value => Err(Error::ExpectedString {
|
||||||
|
actual: value.clone(),
|
||||||
|
}),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Borrows the value stored in `self` as `String`, or returns `Err` if `self` is not a `Value::String`.
|
||||||
|
pub fn as_string_mut(&self) -> Result<RwLockWriteGuard<String>> {
|
||||||
|
match self {
|
||||||
|
Value::String(string) => Ok(string.write()?),
|
||||||
value => Err(Error::ExpectedString {
|
value => Err(Error::ExpectedString {
|
||||||
actual: value.clone(),
|
actual: value.clone(),
|
||||||
}),
|
}),
|
||||||
@ -197,7 +212,7 @@ impl Value {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Borrows the value stored in `self` as `Vec<Value>`, or returns `Err` if `self` is not a `Value::List`.
|
/// Takes ownership of the value stored in `self` as `Vec<Value>`, or returns `Err` if `self` is not a `Value::List`.
|
||||||
pub fn into_inner_list(self) -> Result<List> {
|
pub fn into_inner_list(self) -> Result<List> {
|
||||||
match self {
|
match self {
|
||||||
Value::List(list) => Ok(list),
|
Value::List(list) => Ok(list),
|
||||||
@ -276,11 +291,11 @@ impl Add for Value {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if let (Ok(left), Ok(right)) = (self.as_string(), other.as_string()) {
|
if let (Ok(left), Ok(right)) = (self.as_string(), other.as_string()) {
|
||||||
return Ok(Value::String(left.to_string() + right));
|
return Ok(Value::string(left.to_string() + right.as_str()));
|
||||||
}
|
}
|
||||||
|
|
||||||
if self.is_string() || other.is_string() {
|
if self.is_string() || other.is_string() {
|
||||||
return Ok(Value::String(self.to_string() + &other.to_string()));
|
return Ok(Value::string(self.to_string() + &other.to_string()));
|
||||||
}
|
}
|
||||||
|
|
||||||
let non_number_or_string = if !self.is_number() == !self.is_string() {
|
let non_number_or_string = if !self.is_number() == !self.is_string() {
|
||||||
@ -368,7 +383,9 @@ impl AddAssign for Value {
|
|||||||
(Value::Integer(left), Value::Integer(right)) => *left += right,
|
(Value::Integer(left), Value::Integer(right)) => *left += right,
|
||||||
(Value::Float(left), Value::Float(right)) => *left += right,
|
(Value::Float(left), Value::Float(right)) => *left += right,
|
||||||
(Value::Float(left), Value::Integer(right)) => *left += right as f64,
|
(Value::Float(left), Value::Integer(right)) => *left += right as f64,
|
||||||
(Value::String(left), Value::String(right)) => *left += &right,
|
(Value::String(left), Value::String(right)) => {
|
||||||
|
*left.write().unwrap() += right.read().unwrap().as_str()
|
||||||
|
}
|
||||||
(Value::List(list), value) => list.items_mut().push(value),
|
(Value::List(list), value) => list.items_mut().push(value),
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
@ -405,7 +422,9 @@ impl PartialEq for Value {
|
|||||||
(Value::Integer(left), Value::Integer(right)) => left == right,
|
(Value::Integer(left), Value::Integer(right)) => left == right,
|
||||||
(Value::Float(left), Value::Float(right)) => left == right,
|
(Value::Float(left), Value::Float(right)) => left == right,
|
||||||
(Value::Boolean(left), Value::Boolean(right)) => left == right,
|
(Value::Boolean(left), Value::Boolean(right)) => left == right,
|
||||||
(Value::String(left), Value::String(right)) => left == right,
|
(Value::String(left), Value::String(right)) => {
|
||||||
|
left.read().unwrap().as_str() == right.read().unwrap().as_str()
|
||||||
|
}
|
||||||
(Value::List(left), Value::List(right)) => left == right,
|
(Value::List(left), Value::List(right)) => left == right,
|
||||||
(Value::Map(left), Value::Map(right)) => left == right,
|
(Value::Map(left), Value::Map(right)) => left == right,
|
||||||
(Value::Function(left), Value::Function(right)) => left == right,
|
(Value::Function(left), Value::Function(right)) => left == right,
|
||||||
@ -424,7 +443,11 @@ impl PartialOrd for Value {
|
|||||||
impl Ord for Value {
|
impl Ord for Value {
|
||||||
fn cmp(&self, other: &Self) -> Ordering {
|
fn cmp(&self, other: &Self) -> Ordering {
|
||||||
match (self, other) {
|
match (self, other) {
|
||||||
(Value::String(left), Value::String(right)) => left.cmp(right),
|
(Value::String(left), Value::String(right)) => left
|
||||||
|
.read()
|
||||||
|
.unwrap()
|
||||||
|
.as_str()
|
||||||
|
.cmp(right.read().unwrap().as_str()),
|
||||||
(Value::String(_), _) => Ordering::Greater,
|
(Value::String(_), _) => Ordering::Greater,
|
||||||
(Value::Float(left), Value::Float(right)) => left.total_cmp(right),
|
(Value::Float(left), Value::Float(right)) => left.total_cmp(right),
|
||||||
(Value::Integer(left), Value::Integer(right)) => left.cmp(right),
|
(Value::Integer(left), Value::Integer(right)) => left.cmp(right),
|
||||||
@ -458,7 +481,7 @@ impl Serialize for Value {
|
|||||||
S: Serializer,
|
S: Serializer,
|
||||||
{
|
{
|
||||||
match self {
|
match self {
|
||||||
Value::String(inner) => serializer.serialize_str(inner),
|
Value::String(inner) => serializer.serialize_str(inner.read().unwrap().as_str()),
|
||||||
Value::Float(inner) => serializer.serialize_f64(*inner),
|
Value::Float(inner) => serializer.serialize_f64(*inner),
|
||||||
Value::Integer(inner) => serializer.serialize_i64(*inner),
|
Value::Integer(inner) => serializer.serialize_i64(*inner),
|
||||||
Value::Boolean(inner) => serializer.serialize_bool(*inner),
|
Value::Boolean(inner) => serializer.serialize_bool(*inner),
|
||||||
@ -482,7 +505,7 @@ impl Serialize for Value {
|
|||||||
impl Display for Value {
|
impl Display for Value {
|
||||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||||
match self {
|
match self {
|
||||||
Value::String(string) => write!(f, "{string}"),
|
Value::String(string) => write!(f, "{}", string.read().unwrap()),
|
||||||
Value::Float(float) => write!(f, "{float}"),
|
Value::Float(float) => write!(f, "{float}"),
|
||||||
Value::Integer(int) => write!(f, "{int}"),
|
Value::Integer(int) => write!(f, "{int}"),
|
||||||
Value::Boolean(boolean) => write!(f, "{boolean}"),
|
Value::Boolean(boolean) => write!(f, "{boolean}"),
|
||||||
@ -502,13 +525,13 @@ impl Display for Value {
|
|||||||
|
|
||||||
impl From<String> for Value {
|
impl From<String> for Value {
|
||||||
fn from(string: String) -> Self {
|
fn from(string: String) -> Self {
|
||||||
Value::String(string)
|
Value::string(string)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<&str> for Value {
|
impl From<&str> for Value {
|
||||||
fn from(string: &str) -> Self {
|
fn from(string: &str) -> Self {
|
||||||
Value::String(string.to_string())
|
Value::string(string.to_string())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -552,8 +575,8 @@ impl TryFrom<Value> for String {
|
|||||||
type Error = Error;
|
type Error = Error;
|
||||||
|
|
||||||
fn try_from(value: Value) -> std::result::Result<Self, Self::Error> {
|
fn try_from(value: Value) -> std::result::Result<Self, Self::Error> {
|
||||||
if let Value::String(value) = value {
|
if let Value::String(rw_lock) = value {
|
||||||
Ok(value)
|
Ok(rw_lock.read()?.to_string())
|
||||||
} else {
|
} else {
|
||||||
Err(Error::ExpectedString { actual: value })
|
Err(Error::ExpectedString { actual: value })
|
||||||
}
|
}
|
||||||
@ -721,7 +744,7 @@ impl<'de> Visitor<'de> for ValueVisitor {
|
|||||||
where
|
where
|
||||||
E: serde::de::Error,
|
E: serde::de::Error,
|
||||||
{
|
{
|
||||||
Ok(Value::String(v.to_string()))
|
Ok(Value::string(v.to_string()))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_borrowed_str<E>(self, v: &'de str) -> std::result::Result<Self::Value, E>
|
fn visit_borrowed_str<E>(self, v: &'de str) -> std::result::Result<Self::Value, E>
|
||||||
@ -735,7 +758,7 @@ impl<'de> Visitor<'de> for ValueVisitor {
|
|||||||
where
|
where
|
||||||
E: serde::de::Error,
|
E: serde::de::Error,
|
||||||
{
|
{
|
||||||
Ok(Value::String(v))
|
Ok(Value::string(v))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_bytes<E>(self, v: &[u8]) -> std::result::Result<Self::Value, E>
|
fn visit_bytes<E>(self, v: &[u8]) -> std::result::Result<Self::Value, E>
|
||||||
|
@ -115,14 +115,14 @@ mod value {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn string() {
|
fn string() {
|
||||||
assert_eq!(interpret("\"one\""), Ok(Value::String("one".to_string())));
|
assert_eq!(interpret("\"one\""), Ok(Value::string("one".to_string())));
|
||||||
assert_eq!(interpret("'one'"), Ok(Value::String("one".to_string())));
|
assert_eq!(interpret("'one'"), Ok(Value::string("one".to_string())));
|
||||||
assert_eq!(interpret("`one`"), Ok(Value::String("one".to_string())));
|
assert_eq!(interpret("`one`"), Ok(Value::string("one".to_string())));
|
||||||
assert_eq!(interpret("`'one'`"), Ok(Value::String("'one'".to_string())));
|
assert_eq!(interpret("`'one'`"), Ok(Value::string("'one'".to_string())));
|
||||||
assert_eq!(interpret("'`one`'"), Ok(Value::String("`one`".to_string())));
|
assert_eq!(interpret("'`one`'"), Ok(Value::string("`one`".to_string())));
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
interpret("\"'one'\""),
|
interpret("\"'one'\""),
|
||||||
Ok(Value::String("'one'".to_string()))
|
Ok(Value::string("'one'".to_string()))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -133,7 +133,7 @@ mod value {
|
|||||||
Ok(Value::List(List::with_items(vec![
|
Ok(Value::List(List::with_items(vec![
|
||||||
Value::Integer(1),
|
Value::Integer(1),
|
||||||
Value::Integer(2),
|
Value::Integer(2),
|
||||||
Value::String("foobar".to_string()),
|
Value::string("foobar".to_string()),
|
||||||
])))
|
])))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -143,7 +143,7 @@ mod value {
|
|||||||
let map = Map::new();
|
let map = Map::new();
|
||||||
|
|
||||||
map.set("x".to_string(), Value::Integer(1), None).unwrap();
|
map.set("x".to_string(), Value::Integer(1), None).unwrap();
|
||||||
map.set("foo".to_string(), Value::String("bar".to_string()), None)
|
map.set("foo".to_string(), Value::string("bar".to_string()), None)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
assert_eq!(interpret("{ x = 1, foo = 'bar' }"), Ok(Value::Map(map)));
|
assert_eq!(interpret("{ x = 1, foo = 'bar' }"), Ok(Value::Map(map)));
|
||||||
@ -157,7 +157,7 @@ mod value {
|
|||||||
.unwrap();
|
.unwrap();
|
||||||
map.set(
|
map.set(
|
||||||
"foo".to_string(),
|
"foo".to_string(),
|
||||||
Value::String("bar".to_string()),
|
Value::string("bar".to_string()),
|
||||||
Some(Type::String),
|
Some(Type::String),
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
@ -228,7 +228,7 @@ mod function_call {
|
|||||||
foobar('Hiya')
|
foobar('Hiya')
|
||||||
",
|
",
|
||||||
),
|
),
|
||||||
Ok(Value::String("Hiya".to_string()))
|
Ok(Value::string("Hiya".to_string()))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -256,7 +256,7 @@ mod function_call {
|
|||||||
foobar(() <str> { 'Hiya' })
|
foobar(() <str> { 'Hiya' })
|
||||||
",
|
",
|
||||||
),
|
),
|
||||||
Ok(Value::String("Hiya".to_string()))
|
Ok(Value::string("Hiya".to_string()))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -273,7 +273,7 @@ mod if_else {
|
|||||||
fn r#if() {
|
fn r#if() {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
interpret("if true { 'true' }"),
|
interpret("if true { 'true' }"),
|
||||||
Ok(Value::String("true".to_string()))
|
Ok(Value::string("true".to_string()))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -303,7 +303,7 @@ mod if_else {
|
|||||||
}
|
}
|
||||||
"
|
"
|
||||||
),
|
),
|
||||||
Ok(Value::String("ok".to_string()))
|
Ok(Value::string("ok".to_string()))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -325,7 +325,7 @@ mod if_else {
|
|||||||
}
|
}
|
||||||
"
|
"
|
||||||
),
|
),
|
||||||
Ok(Value::String("ok".to_string()))
|
Ok(Value::string("ok".to_string()))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user