Skip to content

Commit 8fc0fc9

Browse files
committed
Add base64 encode/decode builtins
1 parent 0f654c9 commit 8fc0fc9

9 files changed

Lines changed: 77 additions & 3 deletions

Cargo.lock

Lines changed: 7 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,3 +28,4 @@ thiserror = "2"
2828
once_cell = "1.21.3"
2929
codespan-reporting = "0.12.0"
3030
line-col = "0.2.1"
31+
base64 = "0.22.1"

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,8 @@ See [/spec](./spec/) for more syntax examples.
8383
| `type(value: Value) -> Type` | Get the string representation of a value's type |
8484
| `eq(a: Value, b: Value) -> Bool` | Compare two values for equality |
8585
| `not(value: Bool) -> Bool` | Logical NOT operation on a boolean value |
86+
| `base64encode(value: String) -> String` | Base64 encode a string value |
87+
| `base64decode(value: String) -> String` | Base64 decode a string value |
8688

8789
### Why Backticks For Strings?
8890

spec/valid/call_b64decode.expr

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
(b64decode `SGVsbG8=`)
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
`Hello`

spec/valid/call_b64encode.expr

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
(b64encode `Hello`)
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
`SGVsbG8=`

src/builtins.rs

Lines changed: 59 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ impl<'a> BuiltinFn<'a> {
6363
/// The default set of builtin functions
6464
///
6565
/// This also defines the lookup index for builtins during compilation
66-
pub const DEFAULT_BUILTINS: [BuiltinFn<'a>; 17] = [
66+
pub const DEFAULT_BUILTINS: [BuiltinFn<'a>; 19] = [
6767
BuiltinFn::ID,
6868
BuiltinFn::NOOP,
6969
BuiltinFn::IS_EMPTY,
@@ -81,6 +81,8 @@ impl<'a> BuiltinFn<'a> {
8181
BuiltinFn::TYPE,
8282
BuiltinFn::EQ,
8383
BuiltinFn::NOT,
84+
BuiltinFn::BASE64_ENCODE,
85+
BuiltinFn::BASE64_DECODE,
8486
];
8587

8688
// Builtin Definitions
@@ -546,6 +548,62 @@ impl<'a> BuiltinFn<'a> {
546548

547549
Ok(Value::Bool(!value))
548550
}
551+
552+
/// Return a base64 encoded the [`Value`] passed in
553+
///
554+
/// `(base64_encode ?string_prompt)`
555+
pub const BASE64_ENCODE: BuiltinFn<'static> = BuiltinFn {
556+
name: "b64encode",
557+
args: &[FnArg {
558+
name: "value",
559+
ty: Type::Value,
560+
variadic: false,
561+
}],
562+
return_type: Type::Value,
563+
func: Self::base64_encode,
564+
};
565+
566+
fn base64_encode(args: Vec<Value>) -> ExprResult<Value> {
567+
let string_arg = args
568+
.first()
569+
.expect("should have string expression passed")
570+
.get_string()?;
571+
572+
use base64::prelude::*;
573+
574+
let encoded = BASE64_STANDARD.encode(string_arg);
575+
576+
Ok(Value::String(encoded))
577+
}
578+
579+
/// Return a base64 decoded of the [`Value`] passed in
580+
///
581+
/// `(base64_encode ?string_prompt)`
582+
pub const BASE64_DECODE: BuiltinFn<'static> = BuiltinFn {
583+
name: "b64decode",
584+
args: &[FnArg {
585+
name: "value",
586+
ty: Type::Value,
587+
variadic: false,
588+
}],
589+
return_type: Type::Value,
590+
func: Self::base64_decode,
591+
};
592+
593+
fn base64_decode(args: Vec<Value>) -> ExprResult<Value> {
594+
let string_arg = args
595+
.first()
596+
.expect("should have string expression passed")
597+
.get_string()?;
598+
599+
use base64::prelude::*;
600+
601+
let decoded = BASE64_STANDARD
602+
.decode(string_arg)
603+
.expect("unable to decode");
604+
605+
Ok(Value::String(String::from_utf8(decoded).unwrap()))
606+
}
549607
}
550608

551609
impl<'a> PartialEq for BuiltinFn<'a> {

tests/spec_tests.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,8 @@ fn spec_files_disassembled(#[files("spec/**/*.expr")] path: PathBuf) -> ExprResu
3636
let (args, expected_disassembled) = if let Some((i, _)) = expected_disassembled
3737
.lines()
3838
.next()
39-
.filter(|line| line.starts_with("//")).map(|line| (line.len() + 1, line))
39+
.filter(|line| line.starts_with("//"))
40+
.map(|line| (line.len() + 1, line))
4041
{
4142
expected_disassembled.split_at(i)
4243
} else {
@@ -96,7 +97,8 @@ fn spec_files_interpreted(#[files("spec/**/*.expr")] path: PathBuf) -> ExprResul
9697
let (args, expected_interpreted) = if let Some((i, _)) = expected_interpreted
9798
.lines()
9899
.next()
99-
.filter(|line| line.starts_with("//")).map(|line| (line.len() + 1, line))
100+
.filter(|line| line.starts_with("//"))
101+
.map(|line| (line.len() + 1, line))
100102
{
101103
expected_interpreted.split_at(i)
102104
} else {

0 commit comments

Comments
 (0)