mirror of
https://github.com/nim-lang/Nim.git
synced 2026-01-03 11:42:33 +00:00
Add Base64 safe (#13672)
* Implement RFC-4648 Section-7 * https://github.com/nim-lang/Nim/pull/13672#issuecomment-600993466
This commit is contained in:
@@ -112,6 +112,8 @@ echo f
|
||||
- Added `times.isLeapDay`
|
||||
- Added a new module, `std / compilesettings` for querying the compiler about
|
||||
diverse configuration settings.
|
||||
- `base64` adds URL-Safe Base64, implements RFC-4648 Section-7.
|
||||
|
||||
|
||||
## Library changes
|
||||
|
||||
|
||||
@@ -46,6 +46,13 @@
|
||||
## let decoded = decode("SGVsbG8gV29ybGQ=")
|
||||
## assert decoded == "Hello World"
|
||||
##
|
||||
## URL Safe Base64
|
||||
## ---------------
|
||||
##
|
||||
## .. code-block::nim
|
||||
## import base64
|
||||
## doAssert encode("c\xf7>", safe = true) == "Y_c-"
|
||||
## doAssert encode("c\xf7>", safe = false) == "Y/c+"
|
||||
##
|
||||
## See also
|
||||
## ========
|
||||
@@ -56,9 +63,10 @@
|
||||
|
||||
const
|
||||
cb64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
|
||||
cb64safe = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"
|
||||
invalidChar = 255
|
||||
|
||||
template encodeInternal(s: typed): untyped =
|
||||
template encodeInternal(s: typed, alphabet: string): untyped =
|
||||
## encodes `s` into base64 representation.
|
||||
proc encodeSize(size: int): int =
|
||||
return (size * 4 div 3) + 6
|
||||
@@ -78,7 +86,7 @@ template encodeInternal(s: typed): untyped =
|
||||
inc inputIndex
|
||||
|
||||
template outputChar(x: untyped) =
|
||||
result[outputIndex] = cb64[x and 63]
|
||||
result[outputIndex] = alphabet[x and 63]
|
||||
inc outputIndex
|
||||
|
||||
template outputChar(c: char) =
|
||||
@@ -112,12 +120,18 @@ template encodeInternal(s: typed): untyped =
|
||||
|
||||
result.setLen(outputIndex)
|
||||
|
||||
proc encode*[T: SomeInteger|char](s: openArray[T]): string =
|
||||
proc encode*[T: SomeInteger|char](s: openArray[T], safe = false): string =
|
||||
## Encodes `s` into base64 representation.
|
||||
##
|
||||
## This procedure encodes an openarray (array or sequence) of either integers
|
||||
## or characters.
|
||||
##
|
||||
## If ``safe`` is ``true`` then it will encode using the
|
||||
## URL-Safe and Filesystem-safe standard alphabet characters,
|
||||
## which substitutes ``-`` instead of ``+`` and ``_`` instead of ``/``.
|
||||
## * https://en.wikipedia.org/wiki/Base64#URL_applications
|
||||
## * https://tools.ietf.org/html/rfc4648#page-7
|
||||
##
|
||||
## **See also:**
|
||||
## * `encode proc<#encode,string>`_ for encoding a string
|
||||
## * `decode proc<#decode,string>`_ for decoding a string
|
||||
@@ -125,19 +139,27 @@ proc encode*[T: SomeInteger|char](s: openArray[T]): string =
|
||||
assert encode(['n', 'i', 'm']) == "bmlt"
|
||||
assert encode(@['n', 'i', 'm']) == "bmlt"
|
||||
assert encode([1, 2, 3, 4, 5]) == "AQIDBAU="
|
||||
encodeInternal(s)
|
||||
if safe: encodeInternal(s, cb64safe)
|
||||
else: encodeInternal(s, cb64)
|
||||
|
||||
proc encode*(s: string): string =
|
||||
proc encode*(s: string, safe = false): string =
|
||||
## Encodes ``s`` into base64 representation.
|
||||
##
|
||||
## This procedure encodes a string.
|
||||
##
|
||||
## If ``safe`` is ``true`` then it will encode using the
|
||||
## URL-Safe and Filesystem-safe standard alphabet characters,
|
||||
## which substitutes ``-`` instead of ``+`` and ``_`` instead of ``/``.
|
||||
## * https://en.wikipedia.org/wiki/Base64#URL_applications
|
||||
## * https://tools.ietf.org/html/rfc4648#page-7
|
||||
##
|
||||
## **See also:**
|
||||
## * `encode proc<#encode,openArray[T]>`_ for encoding an openarray
|
||||
## * `decode proc<#decode,string>`_ for decoding a string
|
||||
runnableExamples:
|
||||
assert encode("Hello World") == "SGVsbG8gV29ybGQ="
|
||||
encodeInternal(s)
|
||||
if safe: encodeInternal(s, cb64safe)
|
||||
else: encodeInternal(s, cb64)
|
||||
|
||||
proc encodeMIME*(s: string, lineLen = 75, newLine = "\r\n"): string =
|
||||
## Encodes ``s`` into base64 representation as lines.
|
||||
@@ -232,6 +254,3 @@ proc decode*(s: string): string =
|
||||
outputChar(a shl 2 or b shr 4)
|
||||
outputChar(b shl 4 or c shr 2)
|
||||
result.setLen(outputIndex)
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -39,6 +39,21 @@ proc main() =
|
||||
except ValueError:
|
||||
discard
|
||||
|
||||
block base64urlSafe:
|
||||
doAssert encode("c\xf7>", safe = true) == "Y_c-"
|
||||
doAssert encode("c\xf7>", safe = false) == "Y/c+" # Not a nice URL :(
|
||||
doAssert decode("Y/c+") == decode("Y_c-")
|
||||
# Output must not change with safe=true
|
||||
doAssert encode("Hello World", safe = true) == "SGVsbG8gV29ybGQ="
|
||||
doAssert encode("leasure.", safe = true) == "bGVhc3VyZS4="
|
||||
doAssert encode("easure.", safe = true) == "ZWFzdXJlLg=="
|
||||
doAssert encode("asure.", safe = true) == "YXN1cmUu"
|
||||
doAssert encode("sure.", safe = true) == "c3VyZS4="
|
||||
doAssert encode([1,2,3], safe = true) == "AQID"
|
||||
doAssert encode(['h','e','y'], safe = true) == "aGV5"
|
||||
doAssert encode("", safe = true) == ""
|
||||
doAssert encode("the quick brown dog jumps over the lazy fox", safe = true) == "dGhlIHF1aWNrIGJyb3duIGRvZyBqdW1wcyBvdmVyIHRoZSBsYXp5IGZveA=="
|
||||
|
||||
echo "OK"
|
||||
|
||||
main()
|
||||
|
||||
Reference in New Issue
Block a user