Base64 Encoding in Scheme

Our program demonstrates base64 encoding and decoding in Scheme. Here’s the full source code:

(import (scheme base)
        (scheme write)
        (srfi 60))  ; for base64 encoding/decoding

(define (main)
  ; Here's the string we'll encode/decode.
  (define data "abc123!?$*&()'-=@~")

  ; Scheme doesn't have built-in base64 support, so we use SRFI 60.
  ; This encodes using the standard base64 encoder.
  (define sEnc (base64-encode-string data))
  (display sEnc)
  (newline)

  ; Decoding the base64 string
  (define sDec (base64-decode-string sEnc))
  (display sDec)
  (newline)
  (newline)

  ; Scheme doesn't have a built-in URL-safe base64 encoder,
  ; so we'll use a custom function to replace characters
  (define (url-safe-base64 str)
    (string-map (lambda (c)
                  (case c
                    ((#\+) #\-)
                    ((#\/) #\_)
                    (else c)))
                str))

  ; This encodes using a URL-compatible base64 format
  (define uEnc (url-safe-base64 (base64-encode-string data)))
  (display uEnc)
  (newline)

  ; Decoding the URL-safe base64 string
  (define (url-safe-base64-decode str)
    (base64-decode-string
     (string-map (lambda (c)
                   (case c
                     ((#\-) #\+)
                     ((#\_) #\/)
                     (else c)))
                 str)))

  (define uDec (url-safe-base64-decode uEnc))
  (display uDec)
  (newline))

(main)

To run the program, save it as base64-encoding.scm and use your Scheme interpreter. For example, if you’re using Chez Scheme:

$ scheme --script base64-encoding.scm
YWJjMTIzIT8kKiYoKSctPUB+
abc123!?$*&()'-=@~

YWJjMTIzIT8kKiYoKSctPUB-
abc123!?$*&()'-=@~

Note that Scheme doesn’t have built-in base64 encoding/decoding, so we use SRFI 60 for standard base64. For URL-safe base64, we implement custom functions to replace the characters that differ between standard and URL-safe base64 encodings.

The string encodes to slightly different values with the standard and URL-safe base64 encoders (trailing + vs -), but they both decode to the original string as desired.