feat(tvix/eval): context-aware substring

`substring` has a very funny behavior when it comes to empty strings,
it propagates the context too, this is used in nixpkgs to attach context
to strings without using any builtin: `lib.addContextFrom`.

Change-Id: Id655356799b3485f7519b3d1914c630f9d8416c3
Reviewed-on: https://cl.tvl.fyi/c/depot/+/10448
Autosubmit: raitobezarius <tvl@lahfa.xyz>
Reviewed-by: tazjin <tazjin@tvl.su>
Tested-by: BuildkiteCI
This commit is contained in:
Ryan Lahfa 2023-12-27 18:13:27 +01:00 committed by clbot
parent 375f7eaa59
commit 7dcb37fc52

View file

@ -1081,7 +1081,7 @@ mod pure_builtins {
if x.is_catchable() { if x.is_catchable() {
return Ok(x); return Ok(x);
} }
let x = x.to_str()?; let x = x.to_contextful_str()?;
if beg < 0 { if beg < 0 {
return Err(ErrorKind::IndexOutOfBounds { index: beg }); return Err(ErrorKind::IndexOutOfBounds { index: beg });
@ -1092,7 +1092,7 @@ mod pure_builtins {
// non-negative when the starting index is GTE the // non-negative when the starting index is GTE the
// string's length. // string's length.
if beg >= x.as_str().len() { if beg >= x.as_str().len() {
return Ok(Value::String("".into())); return Ok(Value::String(NixString::new_inherit_context_from(&x, "")));
} }
let end = if len < 0 { let end = if len < 0 {
@ -1101,7 +1101,10 @@ mod pure_builtins {
cmp::min(beg + (len as usize), x.as_str().len()) cmp::min(beg + (len as usize), x.as_str().len())
}; };
Ok(Value::String(x.as_bytes()[beg..end].try_into()?)) Ok(Value::String(NixString::new_inherit_context_from(
&x,
&x[beg..end],
)))
} }
#[builtin("tail")] #[builtin("tail")]