Skip to content

Commit

Permalink
Deprecate gleam/base
Browse files Browse the repository at this point in the history
  • Loading branch information
lpil committed Oct 26, 2023
1 parent fe7ca67 commit 5d10856
Show file tree
Hide file tree
Showing 6 changed files with 188 additions and 133 deletions.
42 changes: 8 additions & 34 deletions src/gleam/base.gleam
Original file line number Diff line number Diff line change
@@ -1,47 +1,21 @@
import gleam/bit_array
import gleam/string

/// Encodes a BitArray into a base 64 encoded string.
///
@deprecated("Please use `base64_encode` in the `gleam/bit_array` module instead.")
pub fn encode64(input: BitArray, padding: Bool) -> String {
let encoded = do_encode64(input)
case padding {
True -> encoded
False -> string.replace(encoded, "=", "")
}
bit_array.base64_encode(input, padding)
}

@external(erlang, "base64", "encode")
@external(javascript, "../gleam_stdlib.mjs", "encode64")
fn do_encode64(a: BitArray) -> String

/// Decodes a base 64 encoded string into a `BitArray`.
///
@deprecated("Please use `base64_decode` in the `gleam/bit_array` module instead.")
pub fn decode64(encoded: String) -> Result(BitArray, Nil) {
let padded = case bit_array.byte_size(bit_array.from_string(encoded)) % 4 {
0 -> encoded
n -> string.append(encoded, string.repeat("=", 4 - n))
}
do_decode64(padded)
bit_array.base64_decode(encoded)
}

@external(erlang, "gleam_stdlib", "base_decode64")
@external(javascript, "../gleam_stdlib.mjs", "decode64")
fn do_decode64(a: String) -> Result(BitArray, Nil)

/// Encodes a `BitArray` into a base 64 encoded string with URL and filename safe alphabet.
///
@deprecated("Please use `base64_url_encode` in the `gleam/bit_array` module instead.")
pub fn url_encode64(input: BitArray, padding: Bool) -> String {
encode64(input, padding)
|> string.replace("+", "-")
|> string.replace("/", "_")
bit_array.base64_url_encode(input, padding)
}

/// Decodes a base 64 encoded string with URL and filename safe alphabet into a `BitArray`.
///
@deprecated("Please use `base64_url_decode` in the `gleam/bit_array` module instead.")
pub fn url_decode64(encoded: String) -> Result(BitArray, Nil) {
encoded
|> string.replace("-", "+")
|> string.replace("_", "/")
|> decode64()
bit_array.base64_url_decode(encoded)
}
47 changes: 47 additions & 0 deletions src/gleam/bit_array.gleam
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
//// BitArrays are a sequence of binary data of any length.

import gleam/string

/// Converts a UTF-8 `String` type into a `BitArray`.
///
@external(erlang, "gleam_stdlib", "identity")
Expand Down Expand Up @@ -100,3 +102,48 @@ fn do_to_string(a: BitArray) -> Result(String, Nil)
@external(erlang, "gleam_stdlib", "bit_array_concat")
@external(javascript, "../gleam_stdlib.mjs", "bit_array_concat")
pub fn concat(bit_arrays: List(BitArray)) -> BitArray

/// Encodes a BitArray into a base 64 encoded string.
///
pub fn base64_encode(input: BitArray, padding: Bool) -> String {
let encoded = encode64(input)
case padding {
True -> encoded
False -> string.replace(encoded, "=", "")
}
}

@external(erlang, "base64", "encode")
@external(javascript, "../gleam_stdlib.mjs", "encode64")
fn encode64(a: BitArray) -> String

/// Decodes a base 64 encoded string into a `BitArray`.
///
pub fn base64_decode(encoded: String) -> Result(BitArray, Nil) {
let padded = case byte_size(from_string(encoded)) % 4 {
0 -> encoded
n -> string.append(encoded, string.repeat("=", 4 - n))
}
decode64(padded)
}

@external(erlang, "gleam_stdlib", "base_decode64")
@external(javascript, "../gleam_stdlib.mjs", "decode64")
fn decode64(a: String) -> Result(BitArray, Nil)

/// Encodes a `BitArray` into a base 64 encoded string with URL and filename safe alphabet.
///
pub fn base64_url_encode(input: BitArray, padding: Bool) -> String {
base64_encode(input, padding)
|> string.replace("+", "-")
|> string.replace("/", "_")
}

/// Decodes a base 64 encoded string with URL and filename safe alphabet into a `BitArray`.
///
pub fn base64_url_decode(encoded: String) -> Result(BitArray, Nil) {
encoded
|> string.replace("-", "+")
|> string.replace("_", "/")
|> base64_decode()
}
84 changes: 8 additions & 76 deletions src/gleam/string.gleam
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,6 @@ import gleam/list
import gleam/option.{type Option, None, Some}
import gleam/order
import gleam/string_builder.{type StringBuilder}
@target(erlang)
import gleam/bit_array
@target(erlang)
import gleam/dynamic.{type Dynamic}
@target(erlang)
import gleam/result

/// Determines if a `String` is empty.
///
Expand Down Expand Up @@ -259,25 +253,9 @@ fn do_slice(string: String, idx: Int, len: Int) -> String {
/// "Lone Gunmen"
/// ```
///
pub fn crop(from string: String, before substring: String) -> String {
do_crop(string, substring)
}

@target(erlang)
fn do_crop(string: String, substring: String) -> String {
string
|> erl_contains(substring)
|> dynamic.string()
|> result.unwrap(string)
}

@target(erlang)
@external(erlang, "string", "find")
fn erl_contains(a: String, b: String) -> Dynamic

@target(javascript)
@external(erlang, "gleam_stdlib", "crop_string")
@external(javascript, "../gleam_stdlib.mjs", "crop_string")
fn do_crop(a: String, b: String) -> String
pub fn crop(from string: String, before substring: String) -> String

/// Drops *n* graphemes from the left side of a `String`.
///
Expand Down Expand Up @@ -330,26 +308,9 @@ pub fn drop_right(from string: String, up_to num_graphemes: Int) -> String {
/// False
/// ```
///
pub fn contains(does haystack: String, contain needle: String) -> Bool {
do_contains(haystack, needle)
}

@target(erlang)
fn do_contains(haystack: String, needle: String) -> Bool {
haystack
|> erl_contains(needle)
|> dynamic.bit_array
|> result.is_ok
}

@target(javascript)
fn do_contains(haystack: String, needle: String) -> Bool {
index_of(haystack, needle) != -1
}

@target(javascript)
@external(javascript, "../gleam_stdlib.mjs", "index_of")
fn index_of(a: String, b: String) -> Int
@external(erlang, "gleam_stdlib", "contains_string")
@external(javascript, "../gleam_stdlib.mjs", "contains_string")
pub fn contains(does haystack: String, contain needle: String) -> Bool

/// Checks whether the first `String` starts with the second one.
///
Expand Down Expand Up @@ -755,7 +716,7 @@ pub fn to_utf_codepoints(string: String) -> List(UtfCodepoint) {

@target(erlang)
fn do_to_utf_codepoints(string: String) -> List(UtfCodepoint) {
do_to_utf_codepoints_impl(bit_array.from_string(string), [])
do_to_utf_codepoints_impl(<<string:utf8>>, [])
|> list.reverse
}

Expand Down Expand Up @@ -803,38 +764,9 @@ fn string_to_codepoint_integer_list(a: String) -> List(Int)
/// "abc"
/// ```
///
pub fn from_utf_codepoints(utf_codepoints: List(UtfCodepoint)) -> String {
do_from_utf_codepoints(utf_codepoints)
}

@target(erlang)
fn do_from_utf_codepoints(utf_codepoints: List(UtfCodepoint)) -> String {
let assert Ok(string) =
do_from_utf_codepoints_impl(utf_codepoints, bit_array.from_string(""))
|> bit_array.to_string
string
}

@target(erlang)
fn do_from_utf_codepoints_impl(
utf_codepoints: List(UtfCodepoint),
acc: BitArray,
) -> BitArray {
case utf_codepoints {
[first, ..rest] ->
do_from_utf_codepoints_impl(rest, <<acc:bits, first:utf8_codepoint>>)
[] -> acc
}
}

@target(javascript)
fn do_from_utf_codepoints(utf_codepoints: List(UtfCodepoint)) -> String {
utf_codepoint_list_to_string(utf_codepoints)
}

@target(javascript)
@external(erlang, "gleam_stdlib", "utf_codepoint_list_to_string")
@external(javascript, "../gleam_stdlib.mjs", "utf_codepoint_list_to_string")
fn utf_codepoint_list_to_string(a: List(UtfCodepoint)) -> String
pub fn from_utf_codepoints(utf_codepoints: List(UtfCodepoint)) -> String

/// Converts an integer to a `UtfCodepoint`.
///
Expand Down
57 changes: 37 additions & 20 deletions src/gleam_stdlib.erl
Original file line number Diff line number Diff line change
@@ -1,31 +1,33 @@
-module(gleam_stdlib).

-export([map_get/2, iodata_append/2, identity/1, decode_int/1, decode_bool/1,
decode_float/1, decode_list/1, decode_option/2,
decode_field/2, parse_int/1, parse_float/1, less_than/2,
string_pop_grapheme/1, string_starts_with/2, wrap_list/1,
string_ends_with/2, string_pad/4, decode_map/1, uri_parse/1,
bit_array_int_to_u32/1, bit_array_int_from_u32/1, decode_result/1,
bit_array_slice/3, decode_bit_array/1, compile_regex/2, regex_scan/2,
percent_encode/1, percent_decode/1, regex_check/2, regex_split/2,
base_decode64/1, parse_query/1, bit_array_concat/1, size_of_tuple/1,
decode_tuple/1, decode_tuple2/1, decode_tuple3/1, decode_tuple4/1,
decode_tuple5/1, decode_tuple6/1, tuple_get/2, classify_dynamic/1,
print/1, println/1, print_error/1, println_error/1, inspect/1,
float_to_string/1, int_from_base_string/2]).
-export([
map_get/2, iodata_append/2, identity/1, decode_int/1, decode_bool/1,
decode_float/1, decode_list/1, decode_option/2, decode_field/2, parse_int/1,
parse_float/1, less_than/2, string_pop_grapheme/1, string_starts_with/2,
wrap_list/1, string_ends_with/2, string_pad/4, decode_map/1, uri_parse/1,
bit_array_int_to_u32/1, bit_array_int_from_u32/1, decode_result/1,
bit_array_slice/3, decode_bit_array/1, compile_regex/2, regex_scan/2,
percent_encode/1, percent_decode/1, regex_check/2, regex_split/2,
base_decode64/1, parse_query/1, bit_array_concat/1, size_of_tuple/1,
decode_tuple/1, decode_tuple2/1, decode_tuple3/1, decode_tuple4/1,
decode_tuple5/1, decode_tuple6/1, tuple_get/2, classify_dynamic/1, print/1,
println/1, print_error/1, println_error/1, inspect/1, float_to_string/1,
int_from_base_string/2, utf_codepoint_list_to_string/1, contains_string/2,
crop_string/2
]).

%% Taken from OTP's uri_string module
-define(DEC2HEX(X),
if ((X) >= 0) andalso ((X) =< 9) -> (X) + $0;
((X) >= 10) andalso ((X) =< 15) -> (X) + $A - 10
end).
if ((X) >= 0) andalso ((X) =< 9) -> (X) + $0;
((X) >= 10) andalso ((X) =< 15) -> (X) + $A - 10
end).

%% Taken from OTP's uri_string module
-define(HEX2DEC(X),
if ((X) >= $0) andalso ((X) =< $9) -> (X) - $0;
((X) >= $A) andalso ((X) =< $F) -> (X) - $A + 10;
((X) >= $a) andalso ((X) =< $f) -> (X) - $a + 10
end).
if ((X) >= $0) andalso ((X) =< $9) -> (X) - $0;
((X) >= $A) andalso ((X) =< $F) -> (X) - $A + 10;
((X) >= $a) andalso ((X) =< $f) -> (X) - $a + 10
end).

-define(is_lowercase_char(X), (X > 96 andalso X < 123)).
-define(is_underscore_char(X), (X == 95)).
Expand Down Expand Up @@ -473,3 +475,18 @@ inspect_maybe_utf8_string(Binary, Acc) ->

float_to_string(Float) when is_float(Float) ->
erlang:iolist_to_binary(io_lib_format:fwrite_g(Float)).

utf_codepoint_list_to_string(List) ->
case unicode:characters_to_binary(List) of
{error, _} -> erlang:error({gleam_error, {string_invalid_utf8, List}});
Binary -> Binary
end.

crop_string(String, Prefix) ->
case string:find(String, Prefix) of
nomatch -> String;
New -> New
end.

contains_string(String, Substring) ->
is_bitstring(string:find(String, Substring)).
5 changes: 2 additions & 3 deletions src/gleam_stdlib.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import {
toBitArray,
NonEmpty,
CustomType,
BitArray,
} from "./gleam.mjs";
import {
CompileError as RegexCompileError,
Expand Down Expand Up @@ -225,8 +224,8 @@ export function crop_string(string, substring) {
return string.substring(string.indexOf(substring));
}

export function index_of(haystack, needle) {
return haystack.indexOf(needle) | 0;
export function contains_string(haystack, needle) {
return haystack.indexOf(needle) >= 0;
}

export function starts_with(haystack, needle) {
Expand Down
Loading

0 comments on commit 5d10856

Please sign in to comment.