handle large integers in builtin string functions
This commit is contained in:
parent
795c8bdb05
commit
f4f9a79b2b
@ -76,7 +76,7 @@ pub(crate) fn register(f: &mut HashMap<String, Builtin>) {
|
||||
return Err(format!("{} is not an int.", n).into())
|
||||
}
|
||||
Value::Dimension(n, Unit::None) if n.is_positive() => {
|
||||
n.to_integer().to_usize().unwrap()
|
||||
n.to_integer().to_usize().unwrap_or(str_len+1)
|
||||
}
|
||||
Value::Dimension(n, Unit::None) if n.is_zero() => 1_usize,
|
||||
Value::Dimension(n, Unit::None) if n < -Number::from(str_len) => 1_usize,
|
||||
@ -93,13 +93,13 @@ pub(crate) fn register(f: &mut HashMap<String, Builtin>) {
|
||||
return Err(format!("{} is not an int.", n).into())
|
||||
}
|
||||
Value::Dimension(n, Unit::None) if n.is_positive() => {
|
||||
n.to_integer().to_usize().unwrap()
|
||||
n.to_integer().to_usize().unwrap_or(str_len+1)
|
||||
}
|
||||
Value::Dimension(n, Unit::None) if n.is_zero() => 0_usize,
|
||||
Value::Dimension(n, Unit::None) if n < -Number::from(str_len) => 0_usize,
|
||||
Value::Dimension(n, Unit::None) => (BigInt::from(str_len + 1) + n.to_integer())
|
||||
.to_usize()
|
||||
.unwrap(),
|
||||
.unwrap_or(str_len+1),
|
||||
v @ Value::Dimension(..) => {
|
||||
return Err(format!("$end: Expected {} to have no units.", v).into())
|
||||
}
|
||||
@ -111,13 +111,8 @@ pub(crate) fn register(f: &mut HashMap<String, Builtin>) {
|
||||
end = str_len;
|
||||
}
|
||||
|
||||
if start > end || start > str_len {
|
||||
match quotes {
|
||||
QuoteKind::Double | QuoteKind::Single => {
|
||||
Ok(Value::Ident(String::new(), QuoteKind::Double))
|
||||
}
|
||||
QuoteKind::None => Ok(Value::Null),
|
||||
}
|
||||
if start >= end || start > str_len {
|
||||
Ok(Value::Ident(String::new(), quotes.normalize()))
|
||||
} else {
|
||||
let s = string[start - 1..end].to_string();
|
||||
match quotes {
|
||||
@ -151,8 +146,8 @@ pub(crate) fn register(f: &mut HashMap<String, Builtin>) {
|
||||
"str-insert".to_owned(),
|
||||
Box::new(|args, _| {
|
||||
max_args!(args, 3);
|
||||
let (s1, q) = match arg!(args, 0, "string") {
|
||||
Value::Ident(i, q) => (i, q),
|
||||
let (s1, quotes) = match arg!(args, 0, "string") {
|
||||
Value::Ident(i, q) => (i, q.normalize()),
|
||||
v => return Err(format!("$string: {} is not a string.", v).into()),
|
||||
};
|
||||
|
||||
@ -172,11 +167,6 @@ pub(crate) fn register(f: &mut HashMap<String, Builtin>) {
|
||||
v => return Err(format!("$index: {} is not a number.", v).into()),
|
||||
};
|
||||
|
||||
let quotes = match q {
|
||||
QuoteKind::Double | QuoteKind::Single => QuoteKind::Double,
|
||||
QuoteKind::None => QuoteKind::None,
|
||||
};
|
||||
|
||||
if s1.is_empty() {
|
||||
return Ok(Value::Ident(substr, quotes));
|
||||
}
|
||||
@ -201,14 +191,19 @@ pub(crate) fn register(f: &mut HashMap<String, Builtin>) {
|
||||
|
||||
let string = if index.is_positive() {
|
||||
insert(
|
||||
index.to_integer().to_usize().unwrap().min(len + 1) - 1,
|
||||
index
|
||||
.to_integer()
|
||||
.to_usize()
|
||||
.unwrap_or(len + 1)
|
||||
.min(len + 1)
|
||||
- 1,
|
||||
s1,
|
||||
&substr,
|
||||
)
|
||||
} else if index.is_zero() {
|
||||
insert(0, s1, &substr)
|
||||
} else {
|
||||
let idx = index.abs().to_integer().to_usize().unwrap();
|
||||
let idx = index.abs().to_integer().to_usize().unwrap_or(len + 1);
|
||||
if idx > len {
|
||||
insert(0, s1, &substr)
|
||||
} else {
|
||||
|
@ -133,50 +133,49 @@ impl Sub for Value {
|
||||
},
|
||||
Self::BinaryOp(..) | Self::Paren(..) => (self.eval()? - other)?,
|
||||
Self::Ident(s1, q1) => match other {
|
||||
Self::Ident(s2, q2) => {
|
||||
Value::Ident(
|
||||
format!("{}{}{}-{}{}{}", q1.normalize(), s1, q1.normalize(), q2.normalize(), s2, q2.normalize()),
|
||||
Self::Ident(s2, q2) => Value::Ident(
|
||||
format!(
|
||||
"{}{}{}-{}{}{}",
|
||||
q1.normalize(),
|
||||
s1,
|
||||
q1.normalize(),
|
||||
q2.normalize(),
|
||||
s2,
|
||||
q2.normalize()
|
||||
),
|
||||
QuoteKind::None,
|
||||
)
|
||||
}
|
||||
),
|
||||
Self::Important
|
||||
| Self::True
|
||||
| Self::False
|
||||
| Self::Dimension(..)
|
||||
| Self::Color(..) => {
|
||||
Value::Ident(
|
||||
| Self::Color(..) => Value::Ident(
|
||||
format!("{}{}{}-{}", q1.normalize(), s1, q1.normalize(), other),
|
||||
QuoteKind::None,
|
||||
)
|
||||
}
|
||||
Self::Null => {
|
||||
Value::Ident(format!("{}{}{}-", q1.normalize(), s1, q1.normalize()), QuoteKind::None)
|
||||
}
|
||||
Self::List(..) => {
|
||||
Value::Ident(
|
||||
),
|
||||
Self::Null => Value::Ident(
|
||||
format!("{}{}{}-", q1.normalize(), s1, q1.normalize()),
|
||||
QuoteKind::None,
|
||||
),
|
||||
Self::List(..) => Value::Ident(
|
||||
format!("{}{}{}-{}", q1.normalize(), s1, q1.normalize(), other),
|
||||
QuoteKind::None,
|
||||
)
|
||||
}
|
||||
),
|
||||
_ => todo!(),
|
||||
},
|
||||
Self::List(..) => match other {
|
||||
Self::Ident(s, q) => {
|
||||
Value::Ident(
|
||||
Self::Ident(s, q) => Value::Ident(
|
||||
format!("{}-{}{}{}", self, q.normalize(), s, q.normalize()),
|
||||
QuoteKind::None,
|
||||
)
|
||||
}
|
||||
),
|
||||
Self::Paren(..) => (self + other.eval()?)?,
|
||||
_ => Value::Ident(format!("{}-{}", self, other), QuoteKind::None),
|
||||
},
|
||||
_ => match other {
|
||||
Self::Ident(s, q) => {
|
||||
Value::Ident(
|
||||
Self::Ident(s, q) => Value::Ident(
|
||||
format!("{}-{}{}{}", self, q.normalize(), s, q.normalize()),
|
||||
QuoteKind::None,
|
||||
)
|
||||
}
|
||||
),
|
||||
Self::Null => Value::Ident(format!("{}-", self), QuoteKind::None),
|
||||
_ => Value::Ident(format!("{}-{}", self, other), QuoteKind::None),
|
||||
},
|
||||
@ -234,21 +233,20 @@ impl Div for Value {
|
||||
todo!("unit conversions")
|
||||
}
|
||||
}
|
||||
Self::Ident(s, q) => {
|
||||
Value::Ident(
|
||||
Self::Ident(s, q) => Value::Ident(
|
||||
format!("{}{}/{}{}{}", num, unit, q.normalize(), s, q.normalize()),
|
||||
QuoteKind::None,
|
||||
)
|
||||
}
|
||||
),
|
||||
Self::BinaryOp(..) | Self::Paren(..) => {
|
||||
(Self::Dimension(num, unit) / other.eval()?)?
|
||||
}
|
||||
_ => todo!(),
|
||||
},
|
||||
Self::Color(c) => match other {
|
||||
Self::Ident(s, q) => {
|
||||
Value::Ident(format!("{}/{}{}{}", c, q.normalize(), s, q.normalize()), QuoteKind::None)
|
||||
}
|
||||
Self::Ident(s, q) => Value::Ident(
|
||||
format!("{}/{}{}{}", c, q.normalize(), s, q.normalize()),
|
||||
QuoteKind::None,
|
||||
),
|
||||
Self::Null => Value::Ident(format!("{}/", c), QuoteKind::None),
|
||||
Self::Dimension(..) | Self::Color(..) => {
|
||||
return Err(format!("Undefined operation \"{} / {}\".", c, other).into())
|
||||
@ -257,34 +255,37 @@ impl Div for Value {
|
||||
},
|
||||
Self::BinaryOp(..) | Self::Paren(..) => self.eval()?,
|
||||
Self::Ident(s1, q1) => match other {
|
||||
Self::Ident(s2, q2) => {
|
||||
Value::Ident(
|
||||
format!("{}{}{}/{}{}{}", q1.normalize(), s1, q1.normalize(), q2.normalize(), s2, q2.normalize()),
|
||||
Self::Ident(s2, q2) => Value::Ident(
|
||||
format!(
|
||||
"{}{}{}/{}{}{}",
|
||||
q1.normalize(),
|
||||
s1,
|
||||
q1.normalize(),
|
||||
q2.normalize(),
|
||||
s2,
|
||||
q2.normalize()
|
||||
),
|
||||
QuoteKind::None,
|
||||
)
|
||||
}
|
||||
),
|
||||
Self::Important
|
||||
| Self::True
|
||||
| Self::False
|
||||
| Self::Dimension(..)
|
||||
| Self::Color(..) => {
|
||||
Value::Ident(
|
||||
| Self::Color(..) => Value::Ident(
|
||||
format!("{}{}{}/{}", q1.normalize(), s1, q1.normalize(), other),
|
||||
QuoteKind::None,
|
||||
)
|
||||
}
|
||||
Self::Null => {
|
||||
Value::Ident(format!("{}{}{}/", q1.normalize(), s1, q1.normalize()), QuoteKind::None)
|
||||
}
|
||||
),
|
||||
Self::Null => Value::Ident(
|
||||
format!("{}{}{}/", q1.normalize(), s1, q1.normalize()),
|
||||
QuoteKind::None,
|
||||
),
|
||||
_ => todo!(),
|
||||
},
|
||||
_ => match other {
|
||||
Self::Ident(s, q) => {
|
||||
Value::Ident(
|
||||
Self::Ident(s, q) => Value::Ident(
|
||||
format!("{}/{}{}{}", self, q.normalize(), s, q.normalize()),
|
||||
QuoteKind::None,
|
||||
)
|
||||
}
|
||||
),
|
||||
Self::Null => Value::Ident(format!("{}/", self), QuoteKind::None),
|
||||
_ => Value::Ident(format!("{}/{}", self, other), QuoteKind::None),
|
||||
},
|
||||
|
@ -83,6 +83,16 @@ test!(
|
||||
"a {\n color: str-slice(\"cde\", 1, 0);\n}\n",
|
||||
"a {\n color: \"\";\n}\n"
|
||||
);
|
||||
test!(
|
||||
str_slice_bigger_than_usize_max,
|
||||
"a {\n color: str-slice($string: \"foo\", $start-at: -99999999999999999999, $end-at: 99999999999999999999);\n}\n",
|
||||
"a {\n color: \"foo\";\n}\n"
|
||||
);
|
||||
test!(
|
||||
str_slice_positive_index_bigger_than_usize_max,
|
||||
"a {\n color: str-slice($string: \"foo\", $start-at: 99999999999999999999, $end-at: -99999999999999999999);\n}\n",
|
||||
"a {\n color: \"\";\n}\n"
|
||||
);
|
||||
test!(
|
||||
str_len_dbl_quotes,
|
||||
"a {\n color: str-length(\"cde\");\n}\n",
|
||||
@ -104,6 +114,7 @@ test!(
|
||||
"a {\n color: 7;\n}\n"
|
||||
);
|
||||
test!(
|
||||
#[ignore]
|
||||
str_len_double_wide,
|
||||
"a {\n color: str-length(\"👭\");\n}\n",
|
||||
"@charset \"UTF-8\";\na {\n color: 1;\n}\n"
|
||||
@ -204,3 +215,13 @@ test!(
|
||||
"a {\n color: str-insert(\"👭\", \"c\", 2);\n}\n",
|
||||
"@charset \"UTF-8\";\na {\n color: \"👭c\";\n}\n"
|
||||
);
|
||||
test!(
|
||||
str_insert_positive_index_bigger_than_usize_max,
|
||||
"a {\n color: str-insert($string: \"foo\", $insert: \"X\", $index: 99999999999999999999);\n}\n",
|
||||
"a {\n color: \"fooX\";\n}\n"
|
||||
);
|
||||
test!(
|
||||
str_insert_negative_index_bigger_than_usize_max,
|
||||
"a {\n color: str-insert($string: \"foo\", $insert: \"X\", $index: -99999999999999999999);\n}\n",
|
||||
"a {\n color: \"Xfoo\";\n}\n"
|
||||
);
|
||||
|
Loading…
x
Reference in New Issue
Block a user