Skip to content

Commit 26ae059

Browse files
timfennisclaude
andcommitted
feat(stdlib): add base64 encode/decode functions 🔐
Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
1 parent 4d81c55 commit 26ae059

5 files changed

Lines changed: 43 additions & 1 deletion

File tree

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
@@ -34,6 +34,7 @@ num = "0.4.3"
3434
once_cell = "1.21.3"
3535
ordered-float = "5.1.0"
3636
yansi = { version = "1.0.1", features = ["detect-tty", "detect-env"] }
37+
base64 = "0.22"
3738
rand = "0.10.0"
3839
rand_chacha = "0.10.0"
3940
regex = "1.12.3"

ndc_stdlib/Cargo.toml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ once_cell.workspace = true
1515
tap.workspace = true
1616

1717
# Optional
18+
base64 = { workspace = true, optional = true }
1819
rand = { workspace = true, optional = true }
1920
regex = { workspace = true, optional = true }
2021
serde_json = { workspace = true, optional = true }
@@ -24,7 +25,8 @@ md5 = { version = "0.8.0", optional = true }
2425
sha1 = { version = "0.10.6", optional = true }
2526

2627
[features]
27-
default = ["crypto", "rand", "regex", "serde"]
28+
default = ["base64", "crypto", "rand", "regex", "serde"]
29+
base64 = ["dep:base64"]
2830
crypto = ["dep:md5", "dep:sha1"]
2931
rand = ["dep:rand"]
3032
regex = ["dep:regex"]

ndc_stdlib/src/base64.rs

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
use ndc_macros::export_module;
2+
3+
#[export_module]
4+
mod internal {
5+
use ::base64::Engine as _;
6+
7+
/// Encodes a string using standard base64 (RFC 4648).
8+
pub fn base64_encode(val: &str) -> String {
9+
::base64::engine::general_purpose::STANDARD.encode(val)
10+
}
11+
12+
/// Decodes a standard base64-encoded string.
13+
pub fn base64_decode(val: &str) -> anyhow::Result<String> {
14+
let bytes = ::base64::engine::general_purpose::STANDARD.decode(val)?;
15+
String::from_utf8(bytes).map_err(anyhow::Error::new)
16+
}
17+
18+
/// Encodes a string using URL-safe base64 without padding (RFC 4648 §5).
19+
pub fn base64_url_encode(val: &str) -> String {
20+
::base64::engine::general_purpose::URL_SAFE_NO_PAD.encode(val)
21+
}
22+
23+
/// Decodes a URL-safe base64-encoded string (no padding required).
24+
pub fn base64_url_decode(val: &str) -> anyhow::Result<String> {
25+
let bytes = ::base64::engine::general_purpose::URL_SAFE_NO_PAD.decode(val)?;
26+
String::from_utf8(bytes).map_err(anyhow::Error::new)
27+
}
28+
}

ndc_stdlib/src/lib.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ pub mod sequence;
1515
pub mod string;
1616
pub mod value;
1717

18+
#[cfg(feature = "base64")]
19+
pub mod base64;
1820
#[cfg(feature = "crypto")]
1921
pub mod crypto;
2022
#[cfg(feature = "rand")]
@@ -26,6 +28,8 @@ pub mod serde;
2628

2729
pub fn register(env: &mut FunctionRegistry<Rc<NativeFunction>>) {
2830
aoc::register(env);
31+
#[cfg(feature = "base64")]
32+
base64::register(env);
2933
cmp::register(env);
3034
#[cfg(feature = "crypto")]
3135
crypto::register(env);

0 commit comments

Comments
 (0)