@@ -82,8 +82,8 @@ limitations under the License.
82
82
map(func, arr)::
83
83
if std.type (func) != "function" then
84
84
error ("std.map first param must be function, got " + std.type (func))
85
- else if std.type (arr) != "array" then
86
- error ("std.map second param must be array, got " + std.type (arr))
85
+ else if std.type (arr) != "array" && std.type (arr) != "string" then
86
+ error ("std.map second param must be array / string , got " + std.type (arr))
87
87
else
88
88
std.makeArray (std.length (arr), function (i) func(arr[i])),
89
89
@@ -685,4 +685,81 @@ limitations under the License.
685
685
local vars = ["%s = %s" % [k, std.manifestPython (conf[k])] for k in std.objectFields (conf)];
686
686
std.join ("\n " , vars + ["" ]),
687
687
688
+
689
+ local base64_table = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/" ,
690
+ local base64_inv = {[base64_table[i]]: i for i in std.range (0 , 63 )},
691
+
692
+ base64(input)::
693
+ local bytes =
694
+ if std.type (input) == "string" then
695
+ std.map (function (c) std.codepoint (c), input)
696
+ else
697
+ input;
698
+
699
+ local aux(arr, i, r) =
700
+ if i >= std.length (arr) then
701
+ r
702
+ else if i + 1 >= std.length (arr) then
703
+ local str =
704
+ // 6 MSB of i
705
+ base64_table[(arr[i] & 252 ) >> 2 ] +
706
+ // 2 LSB of i
707
+ base64_table[(arr[i] & 3 ) << 4 ] +
708
+ "==" ;
709
+ aux(arr, i + 3 , r + str)
710
+ else if i + 2 >= std.length (arr) then
711
+ local str =
712
+ // 6 MSB of i
713
+ base64_table[(arr[i] & 252 ) >> 2 ] +
714
+ // 2 LSB of i, 4 MSB of i+1
715
+ base64_table[(arr[i] & 3 ) << 4 | (arr[i+1 ] & 240 ) >> 4 ] +
716
+ // 4 LSB of i+1
717
+ base64_table[(arr[i+1 ] & 15 ) << 2 ] +
718
+ "=" ;
719
+ aux(arr, i + 3 , r + str)
720
+ else
721
+ local str =
722
+ // 6 MSB of i
723
+ base64_table[(arr[i] & 252 ) >> 2 ] +
724
+ // 2 LSB of i, 4 MSB of i+1
725
+ base64_table[(arr[i] & 3 ) << 4 | (arr[i+1 ] & 240 ) >> 4 ] +
726
+ // 4 LSB of i+1, 2 MSB of i+2
727
+ base64_table[(arr[i+1 ] & 15 ) << 2 | (arr[i+2 ] & 192 ) >> 6 ] +
728
+ // 6 LSB of i+2
729
+ base64_table[(arr[i+2 ] & 63 )];
730
+ aux(arr, i + 3 , r + str);
731
+
732
+ local sanity = std.foldl (function (r, a) r && (a < 256 ), bytes, true );
733
+ if !sanity then
734
+ error "Can only base64 encode strings / arrays of single bytes."
735
+ else
736
+ aux(bytes, 0 , "" ),
737
+
738
+
739
+ base64DecodeBytes(str)::
740
+ if std.length (str) % 4 != 0 then
741
+ error "Not a base64 encoded string \" %s\" " % str
742
+ else
743
+ local aux(str, i, r) =
744
+ if i >= std.length (str) then
745
+ r
746
+ else
747
+ // all 6 bits of i, 2 MSB of i+1
748
+ local n1 = [base64_inv[str[i]] << 2 | (base64_inv[str[i+1 ]] >> 4 )];
749
+ // 4 LSB of i+1, 4MSB of i+2
750
+ local n2 =
751
+ if str[i+2 ] == "=" then []
752
+ else [(base64_inv[str[i+1 ]] & 15 ) << 4 | (base64_inv[str[i+2 ]] >> 2 )];
753
+ // 2 LSB of i+2, all 6 bits of i+3
754
+ local n3 =
755
+ if str[i+3 ] == "=" then []
756
+ else [(base64_inv[str[i+2 ]] & 3 ) << 6 | base64_inv[str[i+3 ]]];
757
+ aux(str, i+4 , r + n1 + n2 + n3);
758
+ aux(str, 0 , []),
759
+
760
+ base64Decode(str)::
761
+ local bytes = std.base64DecodeBytes (str);
762
+ std.join ("" , std.map (function (b) std.char (b), bytes))
763
+
764
+
688
765
}
0 commit comments